//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the section of the AST representing C++ friend
// declarations.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_DECLFRIEND_H
#define LLVM_CLANG_AST_DECLFRIEND_H

#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/TypeLoc.h"
#include "llvm/Support/Compiler.h"

namespace clang {

/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
//  For example:
///
/// @code
/// template <typename T> class A {
///   friend int foo(T);
///   friend class B;
///   friend T; // only in C++0x
///   template <typename U> friend class C;
///   template <typename U> friend A& operator+=(A&, const U&) { ... }
/// };
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
class FriendDecl final
    : public Decl,
      private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
  virtual void anchor();
public:
  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;

private:
  // The declaration that's a friend of this class.
  FriendUnion Friend;

  // A pointer to the next friend in the sequence.
  LazyDeclPtr NextFriend;

  // Location of the 'friend' specifier.
  SourceLocation FriendLoc;

  /// True if this 'friend' declaration is unsupported.  Eventually we
  /// will support every possible friend declaration, but for now we
  /// silently ignore some and set this flag to authorize all access.
  unsigned UnsupportedFriend : 1;

  // The number of "outer" template parameter lists in non-templatic
  // (currently unsupported) friend type declarations, such as
  //     template <class T> friend class A<T>::B;
  unsigned NumTPLists : 31;

  friend class CXXRecordDecl::friend_iterator;
  friend class CXXRecordDecl;

  FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
             SourceLocation FriendL,
             ArrayRef<TemplateParameterList*> FriendTypeTPLists)
    : Decl(Decl::Friend, DC, L),
      Friend(Friend),
      NextFriend(),
      FriendLoc(FriendL),
      UnsupportedFriend(false),
      NumTPLists(FriendTypeTPLists.size()) {
    for (unsigned i = 0; i < NumTPLists; ++i)
      getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
  }

  FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
    : Decl(Decl::Friend, Empty), NextFriend(),
      NumTPLists(NumFriendTypeTPLists) { }

  FriendDecl *getNextFriend() {
    if (!NextFriend.isOffset())
      return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
    return getNextFriendSlowCase();
  }
  FriendDecl *getNextFriendSlowCase();

public:
  static FriendDecl *Create(ASTContext &C, DeclContext *DC,
                            SourceLocation L, FriendUnion Friend_,
                            SourceLocation FriendL,
                            ArrayRef<TemplateParameterList*> FriendTypeTPLists
                            = None);
  static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                        unsigned FriendTypeNumTPLists);

  /// If this friend declaration names an (untemplated but possibly
  /// dependent) type, return the type; otherwise return null.  This
  /// is used for elaborated-type-specifiers and, in C++0x, for
  /// arbitrary friend type declarations.
  TypeSourceInfo *getFriendType() const {
    return Friend.dyn_cast<TypeSourceInfo*>();
  }
  unsigned getFriendTypeNumTemplateParameterLists() const {
    return NumTPLists;
  }
  TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
    assert(N < NumTPLists);
    return getTrailingObjects<TemplateParameterList *>()[N];
  }

  /// If this friend declaration doesn't name a type, return the inner
  /// declaration.
  NamedDecl *getFriendDecl() const {
    return Friend.dyn_cast<NamedDecl*>();
  }

  /// Retrieves the location of the 'friend' keyword.
  SourceLocation getFriendLoc() const {
    return FriendLoc;
  }

  /// Retrieves the source range for the friend declaration.
  SourceRange getSourceRange() const override LLVM_READONLY {
    if (NamedDecl *ND = getFriendDecl()) {
      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
        return FD->getSourceRange();
      if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
        return FTD->getSourceRange();
      if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
        return CTD->getSourceRange();
      if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
        if (DD->getOuterLocStart() != DD->getInnerLocStart())
          return DD->getSourceRange();
      }
      return SourceRange(getFriendLoc(), ND->getLocEnd());
    }
    else if (TypeSourceInfo *TInfo = getFriendType()) {
      SourceLocation StartL =
          (NumTPLists == 0) ? getFriendLoc()
                            : getTrailingObjects<TemplateParameterList *>()[0]
                                  ->getTemplateLoc();
      return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
    }
    else
      return SourceRange(getFriendLoc(), getLocation());
  }

  /// Determines if this friend kind is unsupported.
  bool isUnsupportedFriend() const {
    return UnsupportedFriend;
  }
  void setUnsupportedFriend(bool Unsupported) {
    UnsupportedFriend = Unsupported;
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == Decl::Friend; }

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend TrailingObjects;
};

/// An iterator over the friend declarations of a class.
class CXXRecordDecl::friend_iterator {
  FriendDecl *Ptr;

  friend class CXXRecordDecl;
  explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
public:
  friend_iterator() {}

  typedef FriendDecl *value_type;
  typedef FriendDecl *reference;
  typedef FriendDecl *pointer;
  typedef int difference_type;
  typedef std::forward_iterator_tag iterator_category;

  reference operator*() const { return Ptr; }

  friend_iterator &operator++() {
    assert(Ptr && "attempt to increment past end of friend list");
    Ptr = Ptr->getNextFriend();
    return *this;
  }

  friend_iterator operator++(int) {
    friend_iterator tmp = *this;
    ++*this;
    return tmp;
  }

  bool operator==(const friend_iterator &Other) const {
    return Ptr == Other.Ptr;
  }

  bool operator!=(const friend_iterator &Other) const {
    return Ptr != Other.Ptr;
  }

  friend_iterator &operator+=(difference_type N) {
    assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
    while (N--)
      ++*this;
    return *this;
  }

  friend_iterator operator+(difference_type N) const {
    friend_iterator tmp = *this;
    tmp += N;
    return tmp;
  }
};

inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
  return friend_iterator(getFirstFriend());
}

inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
  return friend_iterator(nullptr);
}

inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
  return friend_range(friend_begin(), friend_end());
}

inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
  assert(!FD->NextFriend && "friend already has next friend?");
  FD->NextFriend = data().FirstFriend;
  data().FirstFriend = FD;
}
  
}

#endif
