summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h')
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h2111
1 files changed, 2111 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
new file mode 100644
index 0000000..c19c200
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -0,0 +1,2111 @@
+//===-- DeclCXX.h - Classes for representing C++ 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 C++ Decl subclasses, other than those for
+// templates (in DeclTemplate.h) and friends (in DeclFriend.h).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLCXX_H
+#define LLVM_CLANG_AST_DECLCXX_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+class ClassTemplateDecl;
+class ClassTemplateSpecializationDecl;
+class CXXBasePath;
+class CXXBasePaths;
+class CXXConstructorDecl;
+class CXXConversionDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class CXXMemberLookupCriteria;
+class CXXFinalOverriderMap;
+class FriendDecl;
+
+/// \brief Represents any kind of function declaration, whether it is a
+/// concrete function or a function template.
+class AnyFunctionDecl {
+ NamedDecl *Function;
+
+ AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
+
+public:
+ AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
+ AnyFunctionDecl(FunctionTemplateDecl *FTD);
+
+ /// \brief Implicily converts any function or function template into a
+ /// named declaration.
+ operator NamedDecl *() const { return Function; }
+
+ /// \brief Retrieve the underlying function or function template.
+ NamedDecl *get() const { return Function; }
+
+ static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
+ return AnyFunctionDecl(ND);
+ }
+};
+
+} // end namespace clang
+
+namespace llvm {
+ /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from
+ /// AnyFunctionDecl to any function or function template declaration.
+ template<> struct simplify_type<const ::clang::AnyFunctionDecl> {
+ typedef ::clang::NamedDecl* SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) {
+ return Val;
+ }
+ };
+ template<> struct simplify_type< ::clang::AnyFunctionDecl>
+ : public simplify_type<const ::clang::AnyFunctionDecl> {};
+
+ // Provide PointerLikeTypeTraits for non-cvr pointers.
+ template<>
+ class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
+ public:
+ static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
+ return F.get();
+ }
+ static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
+ return ::clang::AnyFunctionDecl::getFromNamedDecl(
+ static_cast< ::clang::NamedDecl*>(P));
+ }
+
+ enum { NumLowBitsAvailable = 2 };
+ };
+
+} // end namespace llvm
+
+namespace clang {
+
+/// CXXBaseSpecifier - A base class of a C++ class.
+///
+/// Each CXXBaseSpecifier represents a single, direct base class (or
+/// struct) of a C++ class (or struct). It specifies the type of that
+/// base class, whether it is a virtual or non-virtual base, and what
+/// level of access (public, protected, private) is used for the
+/// derivation. For example:
+///
+/// @code
+/// class A { };
+/// class B { };
+/// class C : public virtual A, protected B { };
+/// @endcode
+///
+/// In this code, C will have two CXXBaseSpecifiers, one for "public
+/// virtual A" and the other for "protected B".
+class CXXBaseSpecifier {
+ /// Range - The source code range that covers the full base
+ /// specifier, including the "virtual" (if present) and access
+ /// specifier (if present).
+ // FIXME: Move over to a TypeLoc!
+ SourceRange Range;
+
+ /// Virtual - Whether this is a virtual base class or not.
+ bool Virtual : 1;
+
+ /// BaseOfClass - Whether this is the base of a class (true) or of a
+ /// struct (false). This determines the mapping from the access
+ /// specifier as written in the source code to the access specifier
+ /// used for semantic analysis.
+ bool BaseOfClass : 1;
+
+ /// Access - Access specifier as written in the source code (which
+ /// may be AS_none). The actual type of data stored here is an
+ /// AccessSpecifier, but we use "unsigned" here to work around a
+ /// VC++ bug.
+ unsigned Access : 2;
+
+ /// BaseType - The type of the base class. This will be a class or
+ /// struct (or a typedef of such).
+ QualType BaseType;
+
+public:
+ CXXBaseSpecifier() { }
+
+ CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
+ : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
+
+ /// getSourceRange - Retrieves the source range that contains the
+ /// entire base specifier.
+ SourceRange getSourceRange() const { return Range; }
+
+ /// isVirtual - Determines whether the base class is a virtual base
+ /// class (or not).
+ bool isVirtual() const { return Virtual; }
+
+ /// \brief Determine whether this base class if a base of a class declared
+ /// with the 'class' keyword (vs. one declared with the 'struct' keyword).
+ bool isBaseOfClass() const { return BaseOfClass; }
+
+ /// getAccessSpecifier - Returns the access specifier for this base
+ /// specifier. This is the actual base specifier as used for
+ /// semantic analysis, so the result can never be AS_none. To
+ /// retrieve the access specifier as written in the source code, use
+ /// getAccessSpecifierAsWritten().
+ AccessSpecifier getAccessSpecifier() const {
+ if ((AccessSpecifier)Access == AS_none)
+ return BaseOfClass? AS_private : AS_public;
+ else
+ return (AccessSpecifier)Access;
+ }
+
+ /// getAccessSpecifierAsWritten - Retrieves the access specifier as
+ /// written in the source code (which may mean that no access
+ /// specifier was explicitly written). Use getAccessSpecifier() to
+ /// retrieve the access specifier for use in semantic analysis.
+ AccessSpecifier getAccessSpecifierAsWritten() const {
+ return (AccessSpecifier)Access;
+ }
+
+ /// getType - Retrieves the type of the base class. This type will
+ /// always be an unqualified class type.
+ QualType getType() const { return BaseType; }
+};
+
+/// CXXRecordDecl - Represents a C++ struct/union/class.
+/// FIXME: This class will disappear once we've properly taught RecordDecl
+/// to deal with C++-specific things.
+class CXXRecordDecl : public RecordDecl {
+
+ friend void TagDecl::startDefinition();
+
+ struct DefinitionData {
+ DefinitionData(CXXRecordDecl *D);
+
+ /// UserDeclaredConstructor - True when this class has a
+ /// user-declared constructor.
+ bool UserDeclaredConstructor : 1;
+
+ /// UserDeclaredCopyConstructor - True when this class has a
+ /// user-declared copy constructor.
+ bool UserDeclaredCopyConstructor : 1;
+
+ /// UserDeclaredCopyAssignment - True when this class has a
+ /// user-declared copy assignment operator.
+ bool UserDeclaredCopyAssignment : 1;
+
+ /// UserDeclaredDestructor - True when this class has a
+ /// user-declared destructor.
+ bool UserDeclaredDestructor : 1;
+
+ /// Aggregate - True when this class is an aggregate.
+ bool Aggregate : 1;
+
+ /// PlainOldData - True when this class is a POD-type.
+ bool PlainOldData : 1;
+
+ /// Empty - true when this class is empty for traits purposes,
+ /// i.e. has no data members other than 0-width bit-fields, has no
+ /// virtual function/base, and doesn't inherit from a non-empty
+ /// class. Doesn't take union-ness into account.
+ bool Empty : 1;
+
+ /// Polymorphic - True when this class is polymorphic, i.e. has at
+ /// least one virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
+ /// Abstract - True when this class is abstract, i.e. has at least
+ /// one pure virtual function, (that can come from a base class).
+ bool Abstract : 1;
+
+ /// HasTrivialConstructor - True when this class has a trivial constructor.
+ ///
+ /// C++ [class.ctor]p5. A constructor is trivial if it is an
+ /// implicitly-declared default constructor and if:
+ /// * its class has no virtual functions and no virtual base classes, and
+ /// * all the direct base classes of its class have trivial constructors, and
+ /// * for all the nonstatic data members of its class that are of class type
+ /// (or array thereof), each such class has a trivial constructor.
+ bool HasTrivialConstructor : 1;
+
+ /// HasTrivialCopyConstructor - True when this class has a trivial copy
+ /// constructor.
+ ///
+ /// C++ [class.copy]p6. A copy constructor for class X is trivial
+ /// if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy constructor, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy constructor;
+ /// otherwise the copy constructor is non-trivial.
+ bool HasTrivialCopyConstructor : 1;
+
+ /// HasTrivialCopyAssignment - True when this class has a trivial copy
+ /// assignment operator.
+ ///
+ /// C++ [class.copy]p11. A copy assignment operator for class X is
+ /// trivial if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy assignment operator, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy assignment
+ /// operator;
+ /// otherwise the copy assignment operator is non-trivial.
+ bool HasTrivialCopyAssignment : 1;
+
+ /// HasTrivialDestructor - True when this class has a trivial destructor.
+ ///
+ /// C++ [class.dtor]p3. A destructor is trivial if it is an
+ /// implicitly-declared destructor and if:
+ /// * all of the direct base classes of its class have trivial destructors
+ /// and
+ /// * for all of the non-static data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial destructor.
+ bool HasTrivialDestructor : 1;
+
+ /// ComputedVisibleConversions - True when visible conversion functions are
+ /// already computed and are available.
+ bool ComputedVisibleConversions : 1;
+
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ CXXBaseSpecifier *Bases;
+
+ /// NumBases - The number of base class specifiers in Bases.
+ unsigned NumBases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ CXXBaseSpecifier *VBases;
+
+ /// NumVBases - The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
+ /// Conversions - Overload set containing the conversion functions
+ /// of this C++ class (but not its inherited conversion
+ /// functions). Each of the entries in this overload set is a
+ /// CXXConversionDecl.
+ UnresolvedSet<4> Conversions;
+
+ /// VisibleConversions - Overload set containing the conversion
+ /// functions of this C++ class and all those inherited conversion
+ /// functions that are visible in this class. Each of the entries
+ /// in this overload set is a CXXConversionDecl or a
+ /// FunctionTemplateDecl.
+ UnresolvedSet<4> VisibleConversions;
+
+ /// Definition - The declaration which defines this record.
+ CXXRecordDecl *Definition;
+
+ /// FirstFriend - The first friend declaration in this class, or
+ /// null if there aren't any. This is actually currently stored
+ /// in reverse order.
+ FriendDecl *FirstFriend;
+
+ } *DefinitionData;
+
+ struct DefinitionData &data() {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
+
+ const struct DefinitionData &data() const {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
+
+ /// \brief The template or declaration that this declaration
+ /// describes or was instantiated from, respectively.
+ ///
+ /// For non-templates, this value will be NULL. For record
+ /// declarations that describe a class template, this will be a
+ /// pointer to a ClassTemplateDecl. For member
+ /// classes of class template specializations, this will be the
+ /// MemberSpecializationInfo referring to the member class that was
+ /// instantiated or specialized.
+ llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
+ TemplateOrInstantiation;
+
+#ifndef NDEBUG
+ void CheckConversionFunction(NamedDecl *D);
+#endif
+
+protected:
+ CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL = SourceLocation());
+
+ ~CXXRecordDecl();
+
+public:
+ /// base_class_iterator - Iterator that traverses the base classes
+ /// of a class.
+ typedef CXXBaseSpecifier* base_class_iterator;
+
+ /// base_class_const_iterator - Iterator that traverses the base
+ /// classes of a class.
+ typedef const CXXBaseSpecifier* base_class_const_iterator;
+
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_iterator>
+ reverse_base_class_iterator;
+
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_const_iterator>
+ reverse_base_class_const_iterator;
+
+ virtual CXXRecordDecl *getCanonicalDecl() {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+ virtual const CXXRecordDecl *getCanonicalDecl() const {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+
+ CXXRecordDecl *getDefinition() const {
+ if (!DefinitionData) return 0;
+ return data().Definition;
+ }
+
+ bool hasDefinition() const { return DefinitionData != 0; }
+
+ static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL = SourceLocation(),
+ CXXRecordDecl* PrevDecl=0,
+ bool DelayTypeCreation = false);
+
+ virtual void Destroy(ASTContext& C);
+
+ bool isDynamicClass() const {
+ return data().Polymorphic || data().NumVBases != 0;
+ }
+
+ /// setBases - Sets the base classes of this struct or class.
+ void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
+
+ /// getNumBases - Retrieves the number of base classes of this
+ /// class.
+ unsigned getNumBases() const { return data().NumBases; }
+
+ base_class_iterator bases_begin() { return data().Bases; }
+ base_class_const_iterator bases_begin() const { return data().Bases; }
+ base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
+ base_class_const_iterator bases_end() const {
+ return bases_begin() + data().NumBases;
+ }
+ reverse_base_class_iterator bases_rbegin() {
+ return reverse_base_class_iterator(bases_end());
+ }
+ reverse_base_class_const_iterator bases_rbegin() const {
+ return reverse_base_class_const_iterator(bases_end());
+ }
+ reverse_base_class_iterator bases_rend() {
+ return reverse_base_class_iterator(bases_begin());
+ }
+ reverse_base_class_const_iterator bases_rend() const {
+ return reverse_base_class_const_iterator(bases_begin());
+ }
+
+ /// getNumVBases - Retrieves the number of virtual base classes of this
+ /// class.
+ unsigned getNumVBases() const { return data().NumVBases; }
+
+ base_class_iterator vbases_begin() { return data().VBases; }
+ base_class_const_iterator vbases_begin() const { return data().VBases; }
+ base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
+ base_class_const_iterator vbases_end() const {
+ return vbases_begin() + data().NumVBases;
+ }
+ reverse_base_class_iterator vbases_rbegin() {
+ return reverse_base_class_iterator(vbases_end());
+ }
+ reverse_base_class_const_iterator vbases_rbegin() const {
+ return reverse_base_class_const_iterator(vbases_end());
+ }
+ reverse_base_class_iterator vbases_rend() {
+ return reverse_base_class_iterator(vbases_begin());
+ }
+ reverse_base_class_const_iterator vbases_rend() const {
+ return reverse_base_class_const_iterator(vbases_begin());
+ }
+
+ /// \brief Determine whether this class has any dependent base classes.
+ bool hasAnyDependentBases() const;
+
+ /// Iterator access to method members. The method iterator visits
+ /// all method members of the class, including non-instance methods,
+ /// special methods, etc.
+ typedef specific_decl_iterator<CXXMethodDecl> method_iterator;
+
+ /// method_begin - Method begin iterator. Iterates in the order the methods
+ /// were declared.
+ method_iterator method_begin() const {
+ return method_iterator(decls_begin());
+ }
+ /// method_end - Method end iterator.
+ method_iterator method_end() const {
+ return method_iterator(decls_end());
+ }
+
+ /// Iterator access to constructor members.
+ typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator;
+
+ ctor_iterator ctor_begin() const {
+ return ctor_iterator(decls_begin());
+ }
+ ctor_iterator ctor_end() const {
+ return ctor_iterator(decls_end());
+ }
+
+ /// An iterator over friend declarations. All of these are defined
+ /// in DeclFriend.h.
+ class friend_iterator;
+ friend_iterator friend_begin() const;
+ friend_iterator friend_end() const;
+ void pushFriendDecl(FriendDecl *FD);
+
+ /// Determines whether this record has any friends.
+ bool hasFriends() const {
+ return data().FirstFriend != 0;
+ }
+
+ /// hasConstCopyConstructor - Determines whether this class has a
+ /// copy constructor that accepts a const-qualified argument.
+ bool hasConstCopyConstructor(ASTContext &Context) const;
+
+ /// getCopyConstructor - Returns the copy constructor for this class
+ CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
+ unsigned TypeQuals) const;
+
+ /// hasConstCopyAssignment - Determines whether this class has a
+ /// copy assignment operator that accepts a const-qualified argument.
+ /// It returns its decl in MD if found.
+ bool hasConstCopyAssignment(ASTContext &Context,
+ const CXXMethodDecl *&MD) const;
+
+ /// addedConstructor - Notify the class that another constructor has
+ /// been added. This routine helps maintain information about the
+ /// class based on which constructors have been added.
+ void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
+
+ /// hasUserDeclaredConstructor - Whether this class has any
+ /// user-declared constructors. When true, a default constructor
+ /// will not be implicitly declared.
+ bool hasUserDeclaredConstructor() const {
+ return data().UserDeclaredConstructor;
+ }
+
+ /// hasUserDeclaredCopyConstructor - Whether this class has a
+ /// user-declared copy constructor. When false, a copy constructor
+ /// will be implicitly declared.
+ bool hasUserDeclaredCopyConstructor() const {
+ return data().UserDeclaredCopyConstructor;
+ }
+
+ /// addedAssignmentOperator - Notify the class that another assignment
+ /// operator has been added. This routine helps maintain information about the
+ /// class based on which operators have been added.
+ void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
+
+ /// hasUserDeclaredCopyAssignment - Whether this class has a
+ /// user-declared copy assignment operator. When false, a copy
+ /// assigment operator will be implicitly declared.
+ bool hasUserDeclaredCopyAssignment() const {
+ return data().UserDeclaredCopyAssignment;
+ }
+
+ /// hasUserDeclaredDestructor - Whether this class has a
+ /// user-declared destructor. When false, a destructor will be
+ /// implicitly declared.
+ bool hasUserDeclaredDestructor() const {
+ return data().UserDeclaredDestructor;
+ }
+
+ /// setUserDeclaredDestructor - Set whether this class has a
+ /// user-declared destructor. If not set by the time the class is
+ /// fully defined, a destructor will be implicitly declared.
+ void setUserDeclaredDestructor(bool UCD) {
+ data().UserDeclaredDestructor = UCD;
+ }
+
+ /// getConversions - Retrieve the overload set containing all of the
+ /// conversion functions in this class.
+ UnresolvedSetImpl *getConversionFunctions() {
+ return &data().Conversions;
+ }
+ const UnresolvedSetImpl *getConversionFunctions() const {
+ return &data().Conversions;
+ }
+
+ typedef UnresolvedSetImpl::iterator conversion_iterator;
+ conversion_iterator conversion_begin() const {
+ return getConversionFunctions()->begin();
+ }
+ conversion_iterator conversion_end() const {
+ return getConversionFunctions()->end();
+ }
+
+ /// Replaces a conversion function with a new declaration.
+ ///
+ /// Returns true if the old conversion was found.
+ bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
+ return getConversionFunctions()->replace(Old, New);
+ }
+
+ /// Removes a conversion function from this class. The conversion
+ /// function must currently be a member of this class. Furthermore,
+ /// this class must currently be in the process of being defined.
+ void removeConversion(const NamedDecl *Old);
+
+ /// getVisibleConversionFunctions - get all conversion functions visible
+ /// in current class; including conversion function templates.
+ const UnresolvedSetImpl *getVisibleConversionFunctions();
+
+ /// addConversionFunction - Registers a conversion function which
+ /// this class declares directly.
+ void addConversionFunction(NamedDecl *Decl) {
+#ifndef NDEBUG
+ CheckConversionFunction(Decl);
+#endif
+
+ // We intentionally don't use the decl's access here because it
+ // hasn't been set yet. That's really just a misdesign in Sema.
+ data().Conversions.addDecl(Decl);
+ }
+
+ /// isAggregate - Whether this class is an aggregate (C++
+ /// [dcl.init.aggr]), which is a class with no user-declared
+ /// constructors, no private or protected non-static data members,
+ /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
+ bool isAggregate() const { return data().Aggregate; }
+
+ /// setAggregate - Set whether this class is an aggregate (C++
+ /// [dcl.init.aggr]).
+ void setAggregate(bool Agg) { data().Aggregate = Agg; }
+
+ /// setMethodAsVirtual - Make input method virtual and set the necesssary
+ /// special function bits and other bits accordingly.
+ void setMethodAsVirtual(FunctionDecl *Method);
+
+ /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
+ /// that is an aggregate that has no non-static non-POD data members, no
+ /// reference data members, no user-defined copy assignment operator and no
+ /// user-defined destructor.
+ bool isPOD() const { return data().PlainOldData; }
+
+ /// setPOD - Set whether this class is a POD-type (C++ [class]p4).
+ void setPOD(bool POD) { data().PlainOldData = POD; }
+
+ /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
+ /// means it has a virtual function, virtual base, data member (other than
+ /// 0-width bit-field) or inherits from a non-empty class. Does NOT include
+ /// a check for union-ness.
+ bool isEmpty() const { return data().Empty; }
+
+ /// Set whether this class is empty (C++0x [meta.unary.prop])
+ void setEmpty(bool Emp) { data().Empty = Emp; }
+
+ /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
+ /// which means that the class contains or inherits a virtual function.
+ bool isPolymorphic() const { return data().Polymorphic; }
+
+ /// setPolymorphic - Set whether this class is polymorphic (C++
+ /// [class.virtual]).
+ void setPolymorphic(bool Poly) { data().Polymorphic = Poly; }
+
+ /// isAbstract - Whether this class is abstract (C++ [class.abstract]),
+ /// which means that the class contains or inherits a pure virtual function.
+ bool isAbstract() const { return data().Abstract; }
+
+ /// setAbstract - Set whether this class is abstract (C++ [class.abstract])
+ void setAbstract(bool Abs) { data().Abstract = Abs; }
+
+ // hasTrivialConstructor - Whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
+
+ // setHasTrivialConstructor - Set whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
+
+ // hasTrivialCopyConstructor - Whether this class has a trivial copy
+ // constructor (C++ [class.copy]p6)
+ bool hasTrivialCopyConstructor() const {
+ return data().HasTrivialCopyConstructor;
+ }
+
+ // setHasTrivialCopyConstructor - Set whether this class has a trivial
+ // copy constructor (C++ [class.copy]p6)
+ void setHasTrivialCopyConstructor(bool TC) {
+ data().HasTrivialCopyConstructor = TC;
+ }
+
+ // hasTrivialCopyAssignment - Whether this class has a trivial copy
+ // assignment operator (C++ [class.copy]p11)
+ bool hasTrivialCopyAssignment() const {
+ return data().HasTrivialCopyAssignment;
+ }
+
+ // setHasTrivialCopyAssignment - Set whether this class has a
+ // trivial copy assignment operator (C++ [class.copy]p11)
+ void setHasTrivialCopyAssignment(bool TC) {
+ data().HasTrivialCopyAssignment = TC;
+ }
+
+ // hasTrivialDestructor - Whether this class has a trivial destructor
+ // (C++ [class.dtor]p3)
+ bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
+
+ // setHasTrivialDestructor - Set whether this class has a trivial destructor
+ // (C++ [class.dtor]p3)
+ void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
+
+ /// \brief If this record is an instantiation of a member class,
+ /// retrieves the member class from which it was instantiated.
+ ///
+ /// This routine will return non-NULL for (non-templated) member
+ /// classes of class templates. For example, given:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// struct A { };
+ /// };
+ /// \endcode
+ ///
+ /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl
+ /// whose parent is the class template specialization X<int>. For
+ /// this declaration, getInstantiatedFromMemberClass() will return
+ /// the CXXRecordDecl X<T>::A. When a complete definition of
+ /// X<int>::A is required, it will be instantiated from the
+ /// declaration returned by getInstantiatedFromMemberClass().
+ CXXRecordDecl *getInstantiatedFromMemberClass() const;
+
+ /// \brief If this class is an instantiation of a member class of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member class RD.
+ void setInstantiationOfMemberClass(CXXRecordDecl *RD,
+ TemplateSpecializationKind TSK);
+
+ /// \brief Retrieves the class template that is described by this
+ /// class declaration.
+ ///
+ /// Every class template is represented as a ClassTemplateDecl and a
+ /// CXXRecordDecl. The former contains template properties (such as
+ /// the template parameter lists) while the latter contains the
+ /// actual description of the template's
+ /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the
+ /// CXXRecordDecl that from a ClassTemplateDecl, while
+ /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
+ /// a CXXRecordDecl.
+ ClassTemplateDecl *getDescribedClassTemplate() const {
+ return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
+ }
+
+ void setDescribedClassTemplate(ClassTemplateDecl *Template) {
+ TemplateOrInstantiation = Template;
+ }
+
+ /// \brief Determine whether this particular class is a specialization or
+ /// instantiation of a class template or member class of a class template,
+ /// and how it was instantiated or specialized.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief Set the kind of specialization or template instantiation this is.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+
+ /// getDefaultConstructor - Returns the default constructor for this class
+ CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
+
+ /// getDestructor - Returns the destructor decl for this class.
+ CXXDestructorDecl *getDestructor(ASTContext &Context) const;
+
+ /// isLocalClass - If the class is a local class [class.local], returns
+ /// the enclosing function declaration.
+ const FunctionDecl *isLocalClass() const {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
+ return RD->isLocalClass();
+
+ return dyn_cast<FunctionDecl>(getDeclContext());
+ }
+
+ /// \brief Determine whether this class is derived from the class \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ bool isDerivedFrom(CXXRecordDecl *Base) const;
+
+ /// \brief Determine whether this class is derived from the type \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \param Paths will contain the paths taken from the current class to the
+ /// given \p Base class.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ ///
+ /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
+ /// tangling input and output in \p Paths
+ bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+
+ /// \brief Determine whether this class is virtually derived from
+ /// the class \p Base.
+ ///
+ /// This routine only determines whether this class is virtually
+ /// derived from \p Base, but does not account for factors that may
+ /// make a Derived -> Base class ill-formed, such as
+ /// private/protected inheritance or multiple, ambiguous base class
+ /// subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \returns true if this class is virtually derived from Base,
+ /// false otherwise.
+ bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const;
+
+ /// \brief Determine whether this class is provably not derived from
+ /// the type \p Base.
+ bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const;
+
+ /// \brief Function type used by forallBases() as a callback.
+ ///
+ /// \param Base the definition of the base class
+ ///
+ /// \returns true if this base matched the search criteria
+ typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
+ void *UserData);
+
+ /// \brief Determines if the given callback holds for all the direct
+ /// or indirect base classes of this type.
+ ///
+ /// The class itself does not count as a base class. This routine
+ /// returns false if the class has non-computable base classes.
+ ///
+ /// \param AllowShortCircuit if false, forces the callback to be called
+ /// for every base class, even if a dependent or non-matching base was
+ /// found.
+ bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
+ bool AllowShortCircuit = true) const;
+
+ /// \brief Function type used by lookupInBases() to determine whether a
+ /// specific base class subobject matches the lookup criteria.
+ ///
+ /// \param Specifier the base-class specifier that describes the inheritance
+ /// from the base class we are trying to match.
+ ///
+ /// \param Path the current path, from the most-derived class down to the
+ /// base named by the \p Specifier.
+ ///
+ /// \param UserData a single pointer to user-specified data, provided to
+ /// lookupInBases().
+ ///
+ /// \returns true if this base matched the search criteria, false otherwise.
+ typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
+
+ /// \brief Look for entities within the base classes of this C++ class,
+ /// transitively searching all base class subobjects.
+ ///
+ /// This routine uses the callback function \p BaseMatches to find base
+ /// classes meeting some search criteria, walking all base class subobjects
+ /// and populating the given \p Paths structure with the paths through the
+ /// inheritance hierarchy that resulted in a match. On a successful search,
+ /// the \p Paths structure can be queried to retrieve the matching paths and
+ /// to determine if there were any ambiguities.
+ ///
+ /// \param BaseMatches callback function used to determine whether a given
+ /// base matches the user-defined search criteria.
+ ///
+ /// \param UserData user data pointer that will be provided to \p BaseMatches.
+ ///
+ /// \param Paths used to record the paths from this class to its base class
+ /// subobjects that match the search criteria.
+ ///
+ /// \returns true if there exists any path from this class to a base class
+ /// subobject that matches the search criteria.
+ bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ CXXBasePaths &Paths) const;
+
+ /// \brief Base-class lookup callback that determines whether the given
+ /// base class specifier refers to a specific class declaration.
+ ///
+ /// This callback can be used with \c lookupInBases() to determine whether
+ /// a given derived class has is a base class subobject of a particular type.
+ /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// base class that we are searching for.
+ static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *BaseRecord);
+
+ /// \brief Base-class lookup callback that determines whether the
+ /// given base class specifier refers to a specific class
+ /// declaration and describes virtual derivation.
+ ///
+ /// This callback can be used with \c lookupInBases() to determine
+ /// whether a given derived class has is a virtual base class
+ /// subobject of a particular type. The user data pointer should
+ /// refer to the canonical CXXRecordDecl of the base class that we
+ /// are searching for.
+ static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *BaseRecord);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a tag with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find tag members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindTagMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name that can be used in a nested-name-specifier.
+ ///
+ /// This callback can be used with \c lookupInBases() to find membes of
+ /// the given name within a C++ class hierarchy that can occur within
+ /// nested-name-specifiers.
+ static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
+
+ /// \brief Retrieve the final overriders for each virtual member
+ /// function in the class hierarchy where this class is the
+ /// most-derived class in the class hierarchy.
+ void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
+
+ /// viewInheritance - Renders and displays an inheritance diagram
+ /// for this C++ class and all of its base classes (transitively) using
+ /// GraphViz.
+ void viewInheritance(ASTContext& Context) const;
+
+ /// MergeAccess - Calculates the access of a decl that is reached
+ /// along a path.
+ static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
+ AccessSpecifier DeclAccess) {
+ assert(DeclAccess != AS_none);
+ if (DeclAccess == AS_private) return AS_none;
+ return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == CXXRecord ||
+ K == ClassTemplateSpecialization ||
+ K == ClassTemplatePartialSpecialization;
+ }
+ static bool classof(const CXXRecordDecl *D) { return true; }
+ static bool classof(const ClassTemplateSpecializationDecl *D) {
+ return true;
+ }
+};
+
+/// CXXMethodDecl - Represents a static or instance method of a
+/// struct/union/class.
+class CXXMethodDecl : public FunctionDecl {
+protected:
+ CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ bool isStatic, StorageClass SCAsWritten, bool isInline)
+ : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None),
+ SCAsWritten, isInline) {}
+
+public:
+ static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic = false,
+ StorageClass SCAsWritten = FunctionDecl::None,
+ bool isInline = false);
+
+ bool isStatic() const { return getStorageClass() == Static; }
+ bool isInstance() const { return !isStatic(); }
+
+ bool isVirtual() const {
+ CXXMethodDecl *CD =
+ cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
+
+ if (CD->isVirtualAsWritten())
+ return true;
+
+ return (CD->begin_overridden_methods() != CD->end_overridden_methods());
+ }
+
+ /// \brief Determine whether this is a usual deallocation function
+ /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
+ /// delete or delete[] operator with a particular signature.
+ bool isUsualDeallocationFunction() const;
+
+ /// \brief Determine whether this is a copy-assignment operator, regardless
+ /// of whether it was declared implicitly or explicitly.
+ bool isCopyAssignmentOperator() const;
+
+ const CXXMethodDecl *getCanonicalDecl() const {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ CXXMethodDecl *getCanonicalDecl() {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+
+ ///
+ void addOverriddenMethod(const CXXMethodDecl *MD);
+
+ typedef const CXXMethodDecl ** method_iterator;
+
+ method_iterator begin_overridden_methods() const;
+ method_iterator end_overridden_methods() const;
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ const CXXRecordDecl *getParent() const {
+ return cast<CXXRecordDecl>(FunctionDecl::getParent());
+ }
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ CXXRecordDecl *getParent() {
+ return const_cast<CXXRecordDecl *>(
+ cast<CXXRecordDecl>(FunctionDecl::getParent()));
+ }
+
+ /// getThisType - Returns the type of 'this' pointer.
+ /// Should only be called for instance methods.
+ QualType getThisType(ASTContext &C) const;
+
+ unsigned getTypeQualifiers() const {
+ return getType()->getAs<FunctionProtoType>()->getTypeQuals();
+ }
+
+ bool hasInlineBody() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXMethodDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= CXXMethod && K <= CXXConversion;
+ }
+};
+
+/// CXXBaseOrMemberInitializer - Represents a C++ base or member
+/// initializer, which is part of a constructor initializer that
+/// initializes one non-static member variable or one base class. For
+/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
+/// initializers:
+///
+/// @code
+/// class A { };
+/// class B : public A {
+/// float f;
+/// public:
+/// B(A& a) : A(a), f(3.14159) { }
+/// };
+/// @endcode
+class CXXBaseOrMemberInitializer {
+ /// \brief Either the base class name (stored as a TypeSourceInfo*) or the
+ /// field being initialized.
+ llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember;
+
+ /// \brief The source location for the field name.
+ SourceLocation MemberLocation;
+
+ /// \brief The argument used to initialize the base or member, which may
+ /// end up constructing an object (when multiple arguments are involved).
+ Stmt *Init;
+
+ /// \brief Stores either the constructor to call to initialize this base or
+ /// member (a CXXConstructorDecl pointer), or stores the anonymous union of
+ /// which the initialized value is a member.
+ ///
+ /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's
+ /// anonymous union data member, this field holds the FieldDecl for the
+ /// member of the anonymous union being initialized.
+ /// @code
+ /// struct X {
+ /// X() : au_i1(123) {}
+ /// union {
+ /// int au_i1;
+ /// float au_f1;
+ /// };
+ /// };
+ /// @endcode
+ /// In above example, BaseOrMember holds the field decl. for anonymous union
+ /// and AnonUnionMember holds field decl for au_i1.
+ FieldDecl *AnonUnionMember;
+
+ /// LParenLoc - Location of the left paren of the ctor-initializer.
+ SourceLocation LParenLoc;
+
+ /// RParenLoc - Location of the right paren of the ctor-initializer.
+ SourceLocation RParenLoc;
+
+ /// IsVirtual - If the initializer is a base initializer, this keeps track
+ /// of whether the base is virtual or not.
+ bool IsVirtual : 1;
+
+ /// IsWritten - Whether or not the initializer is explicitly written
+ /// in the sources.
+ bool IsWritten : 1;
+ /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this
+ /// number keeps track of the textual order of this initializer in the
+ /// original sources, counting from 0; otherwise, if IsWritten is false,
+ /// it stores the number of array index variables stored after this
+ /// object in memory.
+ unsigned SourceOrderOrNumArrayIndices : 14;
+
+ CXXBaseOrMemberInitializer(ASTContext &Context,
+ FieldDecl *Member, SourceLocation MemberLoc,
+ SourceLocation L,
+ Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices);
+
+public:
+ /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
+ explicit
+ CXXBaseOrMemberInitializer(ASTContext &Context,
+ TypeSourceInfo *TInfo, bool IsVirtual,
+ SourceLocation L,
+ Expr *Init,
+ SourceLocation R);
+
+ /// CXXBaseOrMemberInitializer - Creates a new member initializer.
+ explicit
+ CXXBaseOrMemberInitializer(ASTContext &Context,
+ FieldDecl *Member, SourceLocation MemberLoc,
+ SourceLocation L,
+ Expr *Init,
+ SourceLocation R);
+
+ /// \brief Creates a new member initializer that optionally contains
+ /// array indices used to describe an elementwise initialization.
+ static CXXBaseOrMemberInitializer *Create(ASTContext &Context,
+ FieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L,
+ Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices);
+
+ /// \brief Destroy the base or member initializer.
+ void Destroy(ASTContext &Context);
+
+ /// isBaseInitializer - Returns true when this initializer is
+ /// initializing a base class.
+ bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
+
+ /// isMemberInitializer - Returns true when this initializer is
+ /// initializing a non-static data member.
+ bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); }
+
+ /// If this is a base class initializer, returns the type of the
+ /// base class with location information. Otherwise, returns an NULL
+ /// type location.
+ TypeLoc getBaseClassLoc() const;
+
+ /// If this is a base class initializer, returns the type of the base class.
+ /// Otherwise, returns NULL.
+ const Type *getBaseClass() const;
+ Type *getBaseClass();
+
+ /// Returns whether the base is virtual or not.
+ bool isBaseVirtual() const {
+ assert(isBaseInitializer() && "Must call this on base initializer!");
+
+ return IsVirtual;
+ }
+
+ /// \brief Returns the declarator information for a base class initializer.
+ TypeSourceInfo *getBaseClassInfo() const {
+ return BaseOrMember.dyn_cast<TypeSourceInfo *>();
+ }
+
+ /// getMember - If this is a member initializer, returns the
+ /// declaration of the non-static data member being
+ /// initialized. Otherwise, returns NULL.
+ FieldDecl *getMember() {
+ if (isMemberInitializer())
+ return BaseOrMember.get<FieldDecl*>();
+ else
+ return 0;
+ }
+
+ SourceLocation getMemberLocation() const {
+ return MemberLocation;
+ }
+
+ void setMember(FieldDecl *Member) {
+ assert(isMemberInitializer());
+ BaseOrMember = Member;
+ }
+
+ /// \brief Determine the source location of the initializer.
+ SourceLocation getSourceLocation() const;
+
+ /// \brief Determine the source range covering the entire initializer.
+ SourceRange getSourceRange() const;
+
+ /// isWritten - Returns true if this initializer is explicitly written
+ /// in the source code.
+ bool isWritten() const { return IsWritten; }
+
+ /// \brief Return the source position of the initializer, counting from 0.
+ /// If the initializer was implicit, -1 is returned.
+ int getSourceOrder() const {
+ return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1;
+ }
+
+ /// \brief Set the source order of this initializer. This method can only
+ /// be called once for each initializer; it cannot be called on an
+ /// initializer having a positive number of (implicit) array indices.
+ void setSourceOrder(int pos) {
+ assert(!IsWritten &&
+ "calling twice setSourceOrder() on the same initializer");
+ assert(SourceOrderOrNumArrayIndices == 0 &&
+ "setSourceOrder() used when there are implicit array indices");
+ assert(pos >= 0 &&
+ "setSourceOrder() used to make an initializer implicit");
+ IsWritten = true;
+ SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos);
+ }
+
+ FieldDecl *getAnonUnionMember() const {
+ return AnonUnionMember;
+ }
+ void setAnonUnionMember(FieldDecl *anonMember) {
+ AnonUnionMember = anonMember;
+ }
+
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// \brief Determine the number of implicit array indices used while
+ /// described an array member initialization.
+ unsigned getNumArrayIndices() const {
+ return IsWritten ? 0 : SourceOrderOrNumArrayIndices;
+ }
+
+ /// \brief Retrieve a particular array index variable used to
+ /// describe an array member initialization.
+ VarDecl *getArrayIndex(unsigned I) {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ return reinterpret_cast<VarDecl **>(this + 1)[I];
+ }
+ const VarDecl *getArrayIndex(unsigned I) const {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ return reinterpret_cast<const VarDecl * const *>(this + 1)[I];
+ }
+ void setArrayIndex(unsigned I, VarDecl *Index) {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
+ }
+
+ Expr *getInit() { return static_cast<Expr *>(Init); }
+};
+
+/// CXXConstructorDecl - Represents a C++ constructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// explicit X(int); // represented by a CXXConstructorDecl.
+/// };
+/// @endcode
+class CXXConstructorDecl : public CXXMethodDecl {
+ /// IsExplicitSpecified - Whether this constructor declaration has the
+ /// 'explicit' keyword specified.
+ bool IsExplicitSpecified : 1;
+
+ /// ImplicitlyDefined - Whether this constructor was implicitly
+ /// defined by the compiler. When false, the constructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a constructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ /// Support for base and member initializers.
+ /// BaseOrMemberInitializers - The arguments used to initialize the base
+ /// or member.
+ CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
+ unsigned NumBaseOrMemberInitializers;
+
+ CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline,
+ bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false,
+ FunctionDecl::None, isInline),
+ IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
+ BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
+ setImplicit(isImplicitlyDeclared);
+ }
+ virtual void Destroy(ASTContext& C);
+
+public:
+ static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit,
+ bool isInline, bool isImplicitlyDeclared);
+
+ /// isExplicitSpecified - Whether this constructor declaration has the
+ /// 'explicit' keyword specified.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// isExplicit - Whether this constructor was marked "explicit" or not.
+ bool isExplicit() const {
+ return cast<CXXConstructorDecl>(getFirstDeclaration())
+ ->isExplicitSpecified();
+ }
+
+ /// isImplicitlyDefined - Whether this constructor was implicitly
+ /// defined. If false, then this constructor was defined by the
+ /// user. This operation can only be invoked if the constructor has
+ /// already been defined.
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the "
+ "constructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this constructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the constructor "
+ "has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ /// init_iterator - Iterates through the member/base initializer list.
+ typedef CXXBaseOrMemberInitializer **init_iterator;
+
+ /// init_const_iterator - Iterates through the memberbase initializer list.
+ typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() { return BaseOrMemberInitializers; }
+ /// begin() - Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const { return BaseOrMemberInitializers; }
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ }
+ /// end() - Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ }
+
+ /// getNumArgs - Determine the number of arguments used to
+ /// initialize the member or base.
+ unsigned getNumBaseOrMemberInitializers() const {
+ return NumBaseOrMemberInitializers;
+ }
+
+ void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) {
+ NumBaseOrMemberInitializers = numBaseOrMemberInitializers;
+ }
+
+ void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) {
+ BaseOrMemberInitializers = initializers;
+ }
+ /// isDefaultConstructor - Whether this constructor is a default
+ /// constructor (C++ [class.ctor]p5), which can be used to
+ /// default-initialize a class of this type.
+ bool isDefaultConstructor() const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class. @p TypeQuals will be set to the qualifiers on the
+ /// argument type. For example, @p TypeQuals would be set to @c
+ /// QualType::Const for the following copy constructor:
+ ///
+ /// @code
+ /// class X {
+ /// public:
+ /// X(const X&);
+ /// };
+ /// @endcode
+ bool isCopyConstructor(unsigned &TypeQuals) const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class.
+ bool isCopyConstructor() const {
+ unsigned TypeQuals = 0;
+ return isCopyConstructor(TypeQuals);
+ }
+
+ /// isConvertingConstructor - Whether this constructor is a
+ /// converting constructor (C++ [class.conv.ctor]), which can be
+ /// used for user-defined conversions.
+ bool isConvertingConstructor(bool AllowExplicit) const;
+
+ /// \brief Determine whether this is a member template specialization that
+ /// looks like a copy constructor. Such constructors are never used to copy
+ /// an object.
+ bool isCopyConstructorLikeSpecialization() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXConstructorDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXConstructor; }
+};
+
+/// CXXDestructorDecl - Represents a C++ destructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// ~X(); // represented by a CXXDestructorDecl.
+/// };
+/// @endcode
+class CXXDestructorDecl : public CXXMethodDecl {
+ /// ImplicitlyDefined - Whether this destructor was implicitly
+ /// defined by the compiler. When false, the destructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a destructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ FunctionDecl *OperatorDelete;
+
+ CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false,
+ FunctionDecl::None, isInline),
+ ImplicitlyDefined(false), OperatorDelete(0) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
+ static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, bool isInline,
+ bool isImplicitlyDeclared);
+
+ /// isImplicitlyDefined - Whether this destructor was implicitly
+ /// defined. If false, then this destructor was defined by the
+ /// user. This operation can only be invoked if the destructor has
+ /// already been defined.
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the destructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this destructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the destructor has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
+ const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXDestructorDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXDestructor; }
+};
+
+/// CXXConversionDecl - Represents a C++ conversion function within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// operator bool();
+/// };
+/// @endcode
+class CXXConversionDecl : public CXXMethodDecl {
+ /// IsExplicitSpecified - Whether this conversion function declaration is
+ /// marked "explicit", meaning that it can only be applied when the user
+ /// explicitly wrote a cast. This is a C++0x feature.
+ bool IsExplicitSpecified : 1;
+
+ CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicitSpecified)
+ : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false,
+ FunctionDecl::None, isInline),
+ IsExplicitSpecified(isExplicitSpecified) { }
+
+public:
+ static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit);
+
+ /// IsExplicitSpecified - Whether this conversion function declaration is
+ /// marked "explicit", meaning that it can only be applied when the user
+ /// explicitly wrote a cast. This is a C++0x feature.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// isExplicit - Whether this is an explicit conversion operator
+ /// (C++0x only). Explicit conversion operators are only considered
+ /// when the user has explicitly written a cast.
+ bool isExplicit() const {
+ return cast<CXXConversionDecl>(getFirstDeclaration())
+ ->isExplicitSpecified();
+ }
+
+ /// getConversionType - Returns the type that this conversion
+ /// function is converting to.
+ QualType getConversionType() const {
+ return getType()->getAs<FunctionType>()->getResultType();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXConversionDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXConversion; }
+};
+
+/// LinkageSpecDecl - This represents a linkage specification. For example:
+/// extern "C" void foo();
+///
+class LinkageSpecDecl : public Decl, public DeclContext {
+public:
+ /// LanguageIDs - Used to represent the language in a linkage
+ /// specification. The values are part of the serialization abi for
+ /// ASTs and cannot be changed without altering that abi. To help
+ /// ensure a stable abi for this, we choose the DW_LANG_ encodings
+ /// from the dwarf standard.
+ enum LanguageIDs {
+ lang_c = /* DW_LANG_C */ 0x0002,
+ lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004
+ };
+private:
+ /// Language - The language for this linkage specification.
+ LanguageIDs Language;
+
+ /// HadBraces - Whether this linkage specification had curly braces or not.
+ bool HadBraces : 1;
+
+ LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
+ bool Braces)
+ : Decl(LinkageSpec, DC, L),
+ DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
+
+public:
+ static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, LanguageIDs Lang,
+ bool Braces);
+
+ /// \brief Return the language specified by this linkage specification.
+ LanguageIDs getLanguage() const { return Language; }
+
+ /// \brief Set the language specified by this linkage specification.
+ void setLanguage(LanguageIDs L) { Language = L; }
+
+ /// \brief Determines whether this linkage specification had braces in
+ /// its syntactic form.
+ bool hasBraces() const { return HadBraces; }
+
+ /// \brief Set whether this linkage specification has braces in its
+ /// syntactic form.
+ void setHasBraces(bool B) { HadBraces = B; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const LinkageSpecDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == LinkageSpec; }
+ static DeclContext *castToDeclContext(const LinkageSpecDecl *D) {
+ return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D));
+ }
+ static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// UsingDirectiveDecl - Represents C++ using-directive. For example:
+///
+/// using namespace std;
+///
+// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide
+// artificial name, for all using-directives in order to store
+// them in DeclContext effectively.
+class UsingDirectiveDecl : public NamedDecl {
+
+ /// SourceLocation - Location of 'namespace' token.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// IdentLoc - Location of nominated namespace-name identifier.
+ // FIXME: We don't store location of scope specifier.
+ SourceLocation IdentLoc;
+
+ /// NominatedNamespace - Namespace nominated by using-directive.
+ NamedDecl *NominatedNamespace;
+
+ /// Enclosing context containing both using-directive and nominated
+ /// namespace.
+ DeclContext *CommonAncestor;
+
+ /// getUsingDirectiveName - Returns special DeclarationName used by
+ /// using-directives. This is only used by DeclContext for storing
+ /// UsingDirectiveDecls in its lookup structure.
+ static DeclarationName getName() {
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
+ SourceLocation NamespcLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor)
+ : NamedDecl(Decl::UsingDirective, DC, L, getName()),
+ NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc),
+ NominatedNamespace(Nominated),
+ CommonAncestor(CommonAncestor) {
+ }
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Set the source range of the nested-name-specifier that
+ /// qualifies the namespace name.
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Set the nested-name-specifier that qualifes the name of the
+ /// namespace.
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
+ const NamedDecl *getNominatedNamespaceAsWritten() const {
+ return NominatedNamespace;
+ }
+
+ /// getNominatedNamespace - Returns namespace nominated by using-directive.
+ NamespaceDecl *getNominatedNamespace();
+
+ const NamespaceDecl *getNominatedNamespace() const {
+ return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
+ }
+
+ /// setNominatedNamespace - Set the namespace nominataed by the
+ /// using-directive.
+ void setNominatedNamespace(NamedDecl* NS);
+
+ /// \brief Returns the common ancestor context of this using-directive and
+ /// its nominated namespace.
+ DeclContext *getCommonAncestor() { return CommonAncestor; }
+ const DeclContext *getCommonAncestor() const { return CommonAncestor; }
+
+ /// \brief Set the common ancestor context of this using-directive and its
+ /// nominated namespace.
+ void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
+
+ // FIXME: Could omit 'Key' in name.
+ /// getNamespaceKeyLocation - Returns location of namespace keyword.
+ SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
+
+ /// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
+ void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
+
+ /// getIdentLocation - Returns location of identifier.
+ SourceLocation getIdentLocation() const { return IdentLoc; }
+
+ /// setIdentLocation - set the location of the identifier.
+ void setIdentLocation(SourceLocation L) { IdentLoc = L; }
+
+ static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ SourceLocation NamespaceLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingDirectiveDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::UsingDirective; }
+
+ // Friend for getUsingDirectiveName.
+ friend class DeclContext;
+};
+
+/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
+///
+/// @code
+/// namespace Foo = Bar;
+/// @endcode
+class NamespaceAliasDecl : public NamedDecl {
+ SourceLocation AliasLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc.
+ SourceLocation IdentLoc;
+
+ /// Namespace - The Decl that this alias points to. Can either be a
+ /// NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *Namespace;
+
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc, NamedDecl *Namespace)
+ : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
+ QualifierRange(QualifierRange), Qualifier(Qualifier),
+ IdentLoc(IdentLoc), Namespace(Namespace) { }
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifiers the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Set the source range of the nested-name-specifier that qualifies
+ /// the namespace name.
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Set the nested-name-specifier that qualifies the name of the
+ /// namespace.
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// \brief Retrieve the namespace declaration aliased by this directive.
+ NamespaceDecl *getNamespace() {
+ if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
+ return AD->getNamespace();
+
+ return cast<NamespaceDecl>(Namespace);
+ }
+
+ const NamespaceDecl *getNamespace() const {
+ return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
+ }
+
+ /// Returns the location of the alias name, i.e. 'foo' in
+ /// "namespace foo = ns::bar;".
+ SourceLocation getAliasLoc() const { return AliasLoc; }
+
+ /// Set the location o;f the alias name, e.e., 'foo' in
+ /// "namespace foo = ns::bar;".
+ void setAliasLoc(SourceLocation L) { AliasLoc = L; }
+
+ /// Returns the location of the 'namespace' keyword.
+ SourceLocation getNamespaceLoc() const { return getLocation(); }
+
+ /// Returns the location of the identifier in the named namespace.
+ SourceLocation getTargetNameLoc() const { return IdentLoc; }
+
+ /// Set the location of the identifier in the named namespace.
+ void setTargetNameLoc(SourceLocation L) { IdentLoc = L; }
+
+ /// \brief Retrieve the namespace that this alias refers to, which
+ /// may either be a NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *getAliasedNamespace() const { return Namespace; }
+
+ /// \brief Set the namespace or namespace alias pointed to by this
+ /// alias decl.
+ void setAliasedNamespace(NamedDecl *ND) {
+ assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) &&
+ "expecting namespace or namespace alias decl");
+ Namespace = ND;
+ }
+
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const NamespaceAliasDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::NamespaceAlias; }
+};
+
+/// UsingShadowDecl - Represents a shadow declaration introduced into
+/// a scope by a (resolved) using declaration. For example,
+///
+/// namespace A {
+/// void foo();
+/// }
+/// namespace B {
+/// using A::foo(); // <- a UsingDecl
+/// // Also creates a UsingShadowDecl for A::foo in B
+/// }
+///
+class UsingShadowDecl : public NamedDecl {
+ /// The referenced declaration.
+ NamedDecl *Underlying;
+
+ /// The using declaration which introduced this decl.
+ UsingDecl *Using;
+
+ UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target)
+ : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()),
+ Underlying(Target), Using(Using) {
+ IdentifierNamespace = Target->getIdentifierNamespace();
+ setImplicit();
+ }
+
+public:
+ static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target) {
+ return new (C) UsingShadowDecl(DC, Loc, Using, Target);
+ }
+
+ /// \brief Gets the underlying declaration which has been brought into the
+ /// local scope.
+ NamedDecl *getTargetDecl() const { return Underlying; }
+
+ /// \brief Sets the underlying declaration which has been brought into the
+ /// local scope.
+ void setTargetDecl(NamedDecl* ND) { Underlying = ND; }
+
+ /// \brief Gets the using declaration to which this declaration is tied.
+ UsingDecl *getUsingDecl() const { return Using; }
+
+ /// \brief Sets the using declaration that introduces this target
+ /// declaration.
+ void setUsingDecl(UsingDecl* UD) { Using = UD; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingShadowDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
+};
+
+/// UsingDecl - Represents a C++ using-declaration. For example:
+/// using someNameSpace::someIdentifier;
+class UsingDecl : public NamedDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange NestedNameRange;
+
+ /// \brief The source location of the "using" location itself.
+ SourceLocation UsingLocation;
+
+ /// \brief Target nested name specifier.
+ NestedNameSpecifier* TargetNestedName;
+
+ /// \brief The collection of shadow declarations associated with
+ /// this using declaration. This set can change as a class is
+ /// processed.
+ llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
+
+ // \brief Has 'typename' keyword.
+ bool IsTypeName;
+
+ UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
+ SourceLocation UL, NestedNameSpecifier* TargetNNS,
+ DeclarationName Name, bool IsTypeNameArg)
+ : NamedDecl(Decl::Using, DC, L, Name),
+ NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
+ IsTypeName(IsTypeNameArg) {
+ }
+
+public:
+ // FIXME: Should be const?
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getNestedNameRange() { return NestedNameRange; }
+
+ /// \brief Set the source range of the nested-name-specifier.
+ void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
+
+ // FIXME; Should be const?
+ // FIXME: Naming is inconsistent with other get*Loc functions.
+ /// \brief Returns the source location of the "using" keyword.
+ SourceLocation getUsingLocation() { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLocation(SourceLocation L) { UsingLocation = L; }
+
+
+ /// \brief Get the target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameDecl() {
+ return TargetNestedName;
+ }
+
+ /// \brief Set the target nested name declaration.
+ void setTargetNestedNameDecl(NestedNameSpecifier *NNS) {
+ TargetNestedName = NNS;
+ }
+
+ /// \brief Return true if the using declaration has 'typename'.
+ bool isTypeName() const { return IsTypeName; }
+
+ /// \brief Sets whether the using declaration has 'typename'.
+ void setTypeName(bool TN) { IsTypeName = TN; }
+
+ typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
+ shadow_iterator shadow_begin() const { return Shadows.begin(); }
+ shadow_iterator shadow_end() const { return Shadows.end(); }
+
+ void addShadowDecl(UsingShadowDecl *S) {
+ assert(S->getUsingDecl() == this);
+ if (!Shadows.insert(S)) {
+ assert(false && "declaration already in set");
+ }
+ }
+ void removeShadowDecl(UsingShadowDecl *S) {
+ assert(S->getUsingDecl() == this);
+ if (!Shadows.erase(S)) {
+ assert(false && "declaration not in set");
+ }
+ }
+
+ /// \brief Return the number of shadowed declarations associated with this
+ /// using declaration.
+ unsigned getNumShadowDecls() const {
+ return Shadows.size();
+ }
+
+ static UsingDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
+ NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::Using; }
+};
+
+/// UnresolvedUsingValueDecl - Represents a dependent using
+/// declaration which was not marked with 'typename'. Unlike
+/// non-dependent using declarations, these *only* bring through
+/// non-types; otherwise they would break two-phase lookup.
+///
+/// template <class T> class A : public Base<T> {
+/// using Base<T>::foo;
+/// };
+class UnresolvedUsingValueDecl : public ValueDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
+ SourceLocation UsingLoc, SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName)
+ : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TargetNestedNameSpecifier(TargetNNS)
+ { }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+ /// \brief Set the source range coverting the nested-name-specifier preceding
+ /// the namespace name.
+ void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
+
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Set the nested name declaration.
+ void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
+ TargetNestedNameSpecifier = NNS;
+ }
+
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+
+ static UnresolvedUsingValueDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingValue; }
+};
+
+/// UnresolvedUsingTypenameDecl - Represents a dependent using
+/// declaration which was marked with 'typename'.
+///
+/// template <class T> class A : public Base<T> {
+/// using typename Base<T>::foo;
+/// };
+///
+/// The type associated with a unresolved using typename decl is
+/// currently always a typename type.
+class UnresolvedUsingTypenameDecl : public TypeDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ /// \brief The source location of the 'typename' keyword
+ SourceLocation TypenameLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+ : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
+ { }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+ /// \brief Set the source range coverting the nested-name-specifier preceding
+ /// the namespace name.
+ void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
+
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Set the nested name declaration.
+ void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
+ TargetNestedNameSpecifier = NNS;
+ }
+
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+
+ /// \brief Returns the source location of the 'typename' keyword.
+ SourceLocation getTypenameLoc() const { return TypenameLocation; }
+
+ /// \brief Set the source location of the 'typename' keyword.
+ void setTypenameLoc(SourceLocation L) { TypenameLocation = L; }
+
+ static UnresolvedUsingTypenameDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingTypename; }
+};
+
+/// StaticAssertDecl - Represents a C++0x static_assert declaration.
+class StaticAssertDecl : public Decl {
+ Expr *AssertExpr;
+ StringLiteral *Message;
+
+ StaticAssertDecl(DeclContext *DC, SourceLocation L,
+ Expr *assertexpr, StringLiteral *message)
+ : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
+
+public:
+ static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, Expr *AssertExpr,
+ StringLiteral *Message);
+
+ Expr *getAssertExpr() { return AssertExpr; }
+ const Expr *getAssertExpr() const { return AssertExpr; }
+
+ StringLiteral *getMessage() { return Message; }
+ const StringLiteral *getMessage() const { return Message; }
+
+ virtual ~StaticAssertDecl();
+ virtual void Destroy(ASTContext& C);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(StaticAssertDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::StaticAssert; }
+};
+
+/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
+/// into a diagnostic with <<.
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ AccessSpecifier AS);
+
+} // end namespace clang
+
+#endif
OpenPOWER on IntegriCloud