diff options
author | dim <dim@FreeBSD.org> | 2010-09-17 15:54:40 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2010-09-17 15:54:40 +0000 |
commit | 36c49e3f258dced101949edabd72e9bc3f1dedc4 (patch) | |
tree | 0bbe07708f7571f8b5291f6d7b96c102b7c99dee /include/clang/AST | |
parent | fc84956ac8b7cd244ef30e7a4d4d38a58dec5904 (diff) | |
download | FreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.zip FreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.tar.gz |
Vendor import of clang r114020 (from the release_28 branch):
http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020
Approved by: rpaulo (mentor)
Diffstat (limited to 'include/clang/AST')
30 files changed, 2606 insertions, 2050 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 0611395..84833c0 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -18,9 +18,10 @@ namespace clang { class ASTContext; class CXXRecordDecl; class DeclGroupRef; - class TagDecl; class HandleTagDeclDefinition; + class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer + class TagDecl; class VarDecl; /// ASTConsumer - This is an abstract interface that should be implemented by @@ -48,6 +49,11 @@ public: /// elements). Use Decl::getNextDeclarator() to walk the chain. virtual void HandleTopLevelDecl(DeclGroupRef D); + /// HandleInterestingDecl - Handle the specified interesting declaration. This + /// is called by the AST reader when deserializing things that might interest + /// the consumer. The default implementation forwards to HandleTopLevelDecl. + virtual void HandleInterestingDecl(DeclGroupRef D); + /// HandleTranslationUnit - This method is called when the ASTs for entire /// translation unit have been parsed. virtual void HandleTranslationUnit(ASTContext &Ctx) {} @@ -80,6 +86,12 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// \brief If the consumer is interested in entities being deserialized from + /// AST files, it should return a pointer to a ASTDeserializationListener here + /// + /// The return type is void* because ASTDS lives in Frontend. + virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; } + /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3799451..ae4ee94 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -50,6 +49,7 @@ namespace clang { class SelectorTable; class SourceManager; class TargetInfo; + class CXXABI; // Decls class DeclContext; class CXXMethodDecl; @@ -198,7 +198,7 @@ class ASTContext { /// /// Since so few decls have attrs, we keep them in a hash map instead of /// wasting space in the Decl class. - llvm::DenseMap<const Decl*, Attr*> DeclAttrs; + llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs; /// \brief Keeps track of the static data member templates from which /// static data members of class template specializations were instantiated. @@ -275,13 +275,18 @@ class ASTContext { /// this ASTContext object. LangOptions LangOpts; - /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. - bool FreeMemory; - llvm::MallocAllocator MallocAlloc; + /// \brief The allocator used to create AST objects. + /// + /// AST objects are never destructed; rather, all memory associated with the + /// AST objects will be released when the ASTContext itself is destroyed. llvm::BumpPtrAllocator BumpAlloc; /// \brief Allocator for partial diagnostics. PartialDiagnostic::StorageAllocator DiagAllocator; + + /// \brief The current C++ ABI. + llvm::OwningPtr<CXXABI> ABI; + CXXABI *createCXXABI(const TargetInfo &T); public: const TargetInfo &Target; @@ -301,13 +306,9 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } void *Allocate(unsigned Size, unsigned Align = 8) { - return FreeMemory ? MallocAlloc.Allocate(Size, Align) : - BumpAlloc.Allocate(Size, Align); - } - void Deallocate(void *Ptr) { - if (FreeMemory) - MallocAlloc.Deallocate(Ptr); + return BumpAlloc.Allocate(Size, Align); } + void Deallocate(void *Ptr) { } PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; @@ -320,10 +321,10 @@ public: } /// \brief Retrieve the attributes for the given declaration. - Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } + AttrVec& getDeclAttrs(const Decl *D); /// \brief Erase the attributes corresponding to the given declaration. - void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } + void eraseDeclAttrs(const Decl *D); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -393,7 +394,7 @@ public: ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, - bool FreeMemory = true, unsigned size_reserve=0); + unsigned size_reserve); ~ASTContext(); @@ -520,7 +521,7 @@ public: llvm::SmallVectorImpl<const Expr *> &Layout); /// This builds the struct used for __block variables. - QualType BuildByRefType(const char *DeclName, QualType Ty); + QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty); /// Returns true iff we need copy/dispose helpers for the given type. bool BlockRequiresCopying(QualType Ty); @@ -873,7 +874,8 @@ public: return getExtQualType(T, Qs); } - DeclarationName getNameForTemplate(TemplateName Name); + DeclarationNameInfo getNameForTemplate(TemplateName Name, + SourceLocation NameLoc); TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -909,6 +911,11 @@ public: /// Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; + /// areCompatibleVectorTypes - Return true if the given vector types either + /// are of the same unqualified type or if one is GCC and other - equivalent + /// AltiVec vector type. + bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); + /// isObjCNSObjectType - Return true if this is an NSObject object with /// its NSObject attribute set. bool isObjCNSObjectType(QualType Ty) const; @@ -1002,13 +1009,12 @@ public: /// of class definition. const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); - void CollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<FieldDecl*> &Fields); - void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); - void CollectNonClassIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -1067,8 +1073,6 @@ public: bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); - /// \brief Retrieves the "canonical" declaration of - /// \brief Retrieves the "canonical" nested name specifier for a /// given nested name specifier. /// @@ -1218,7 +1222,8 @@ public: //===--------------------------------------------------------------------===// /// Compatibility predicates used to check assignment expressions. - bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 + bool typesAreCompatible(QualType T1, QualType T2, + bool CompareUnqualified = false); // C99 6.2.7p1 bool typesAreBlockPointerCompatible(QualType, QualType); @@ -1235,6 +1240,8 @@ public: bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ForCompare); + bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS); + // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1246,10 +1253,13 @@ public: bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); - + bool canBindObjCObjectType(QualType To, QualType From); + // Functions for calculating composite types - QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); - QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); + QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, + bool Unqualified = false); + QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, + bool Unqualified = false); QualType mergeObjCGCQualifiers(QualType, QualType); @@ -1257,6 +1267,10 @@ public: /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) /// and returns the result type of that conversion. QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); + + void ResetObjCLayout(const ObjCContainerDecl *CD) { + ObjCLayouts[CD] = 0; + } //===--------------------------------------------------------------------===// // Integer Predicates @@ -1337,6 +1351,17 @@ public: /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); + GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD); + GVALinkage GetGVALinkageForVariable(const VarDecl *VD); + + /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH + /// lazily, only when used; this is only relevant for function or file scoped + /// var definitions. + /// + /// \returns true if the function/var must be CodeGen'ed/deserialized even if + /// it is not used. + bool DeclMustBeEmitted(const Decl *D); + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// @@ -1386,7 +1411,7 @@ private: const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); - + private: /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 7975c43..9380058 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -14,8 +14,8 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H -#include "clang/AST/Type.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 9faa62e..62ca49f 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -15,8 +15,11 @@ #define LLVM_CLANG_AST_ATTR_H #include "llvm/Support/Casting.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "clang/Basic/AttrKinds.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" #include <cassert> #include <cstring> #include <algorithm> @@ -27,28 +30,39 @@ namespace clang { class IdentifierInfo; class ObjCInterfaceDecl; class Expr; + class QualType; + class FunctionDecl; + class TypeSourceInfo; } // Defined in ASTContext.h void *operator new(size_t Bytes, clang::ASTContext &C, size_t Alignment = 16) throw (); +// FIXME: Being forced to not have a default argument here due to redeclaration +// rules on default arguments sucks +void *operator new[](size_t Bytes, clang::ASTContext &C, + size_t Alignment) throw (); // It is good practice to pair new/delete operators. Also, MSVC gives many // warnings if a matching delete overload is not declared, even though the // throw() spec guarantees it will not be implicitly called. void operator delete(void *Ptr, clang::ASTContext &C, size_t) throw (); +void operator delete[](void *Ptr, clang::ASTContext &C, size_t) + throw (); namespace clang { /// Attr - This represents one attribute. class Attr { private: - Attr *Next; - attr::Kind AttrKind; + SourceLocation Loc; + unsigned AttrKind : 16; bool Inherited : 1; protected: + virtual ~Attr(); + void* operator new(size_t bytes) throw() { assert(0 && "Attrs cannot be allocated with regular 'new'."); return 0; @@ -57,41 +71,36 @@ protected: assert(0 && "Attrs cannot be released with regular 'delete'."); } -protected: - Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} - virtual ~Attr() { - assert(Next == 0 && "Destroy didn't work"); +public: + // Forward so that the regular new and delete do not hide global ones. + void* operator new(size_t Bytes, ASTContext &C, + size_t Alignment = 16) throw() { + return ::operator new(Bytes, C, Alignment); } + void operator delete(void *Ptr, ASTContext &C, + size_t Alignment) throw() { + return ::operator delete(Ptr, C, Alignment); + } + +protected: + Attr(attr::Kind AK, SourceLocation L) + : Loc(L), AttrKind(AK), Inherited(false) {} + public: - virtual void Destroy(ASTContext &C); /// \brief Whether this attribute should be merged to new /// declarations. virtual bool isMerged() const { return true; } - attr::Kind getKind() const { return AttrKind; } - - Attr *getNext() { return Next; } - const Attr *getNext() const { return Next; } - void setNext(Attr *next) { Next = next; } - - template<typename T> const T *getNext() const { - for (const Attr *attr = getNext(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast<T>(attr)) - return V; - return 0; + attr::Kind getKind() const { + return static_cast<attr::Kind>(AttrKind); } - bool isInherited() const { return Inherited; } - void setInherited(bool value) { Inherited = value; } - - void addAttr(Attr *attr) { - assert((attr != 0) && "addAttr(): attr is null"); + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } - // FIXME: This doesn't preserve the order in any way. - attr->Next = Next; - Next = attr; - } + bool isInherited() const { return Inherited; } + void setInherited(bool I) { Inherited = I; } // Clone this attribute. virtual Attr* clone(ASTContext &C) const = 0; @@ -101,490 +110,112 @@ public: }; #include "clang/AST/Attrs.inc" - -class AttrWithString : public Attr { -private: - const char *Str; - unsigned StrLen; -protected: - AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s); - llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); } - void ReplaceString(ASTContext &C, llvm::StringRef newS); -public: - virtual void Destroy(ASTContext &C); -}; - -#define DEF_SIMPLE_ATTR(ATTR) \ -class ATTR##Attr : public Attr { \ -public: \ - ATTR##Attr() : Attr(attr::ATTR) {} \ - virtual Attr *clone(ASTContext &C) const; \ - static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \ - static bool classof(const ATTR##Attr *A) { return true; } \ -} -DEF_SIMPLE_ATTR(Packed); - -/// \brief Attribute for specifying a maximum field alignment; this is only -/// valid on record decls. -class MaxFieldAlignmentAttr : public Attr { - unsigned Alignment; - -public: - MaxFieldAlignmentAttr(unsigned alignment) - : Attr(attr::MaxFieldAlignment), Alignment(alignment) {} +/// AttrVec - A vector of Attr, which is how they are stored on the AST. +typedef llvm::SmallVector<Attr*, 2> AttrVec; +typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec; - /// getAlignment - The specified alignment in bits. - unsigned getAlignment() const { return Alignment; } - - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::MaxFieldAlignment; - } - static bool classof(const MaxFieldAlignmentAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AlignMac68k); - -/// \brief Atribute for specifying the alignment of a variable or type. -/// -/// This node will either contain the precise Alignment (in bits, not bytes!) -/// or will contain the expression for the alignment attribute in the case of -/// a dependent expression within a class or function template. At template -/// instantiation time these are transformed into concrete attributes. -class AlignedAttr : public Attr { - unsigned Alignment; - Expr *AlignmentExpr; -public: - AlignedAttr(unsigned alignment) - : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {} - AlignedAttr(Expr *E) - : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {} - - /// getAlignmentExpr - Get a dependent alignment expression if one is present. - Expr *getAlignmentExpr() const { - return AlignmentExpr; - } - - /// isDependent - Is the alignment a dependent expression - bool isDependent() const { - return getAlignmentExpr(); - } +/// DestroyAttrs - Destroy the contents of an AttrVec. +inline void DestroyAttrs (AttrVec& V, ASTContext &C) { +} - /// getAlignment - The specified alignment in bits. Requires !isDependent(). - unsigned getAlignment() const { - assert(!isDependent() && "Cannot get a value dependent alignment"); - return Alignment; - } +/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only +/// providing attributes that are of a specifc type. +template <typename SpecificAttr> +class specific_attr_iterator { + /// Current - The current, underlying iterator. + /// In order to ensure we don't dereference an invalid iterator unless + /// specifically requested, we don't necessarily advance this all the + /// way. Instead, we advance it when an operation is requested; if the + /// operation is acting on what should be a past-the-end iterator, + /// then we offer no guarantees, but this way we do not dererence a + /// past-the-end iterator when we move to a past-the-end position. + mutable AttrVec::const_iterator Current; - /// getMaxAlignment - Get the maximum alignment of attributes on this list. - unsigned getMaxAlignment() const { - const AlignedAttr *Next = getNext<AlignedAttr>(); - if (Next) - return std::max(Next->getMaxAlignment(), getAlignment()); - else - return getAlignment(); + void AdvanceToNext() const { + while (!llvm::isa<SpecificAttr>(*Current)) + ++Current; } - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Aligned; + void AdvanceToNext(AttrVec::const_iterator I) const { + while (Current != I && !llvm::isa<SpecificAttr>(*Current)) + ++Current; } - static bool classof(const AlignedAttr *A) { return true; } -}; -class AnnotateAttr : public AttrWithString { public: - AnnotateAttr(ASTContext &C, llvm::StringRef ann) - : AttrWithString(attr::Annotate, C, ann) {} - - llvm::StringRef getAnnotation() const { return getString(); } + typedef SpecificAttr* value_type; + typedef SpecificAttr* reference; + typedef SpecificAttr* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; - virtual Attr* clone(ASTContext &C) const; + specific_attr_iterator() : Current() { } + explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { } - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Annotate; + reference operator*() const { + AdvanceToNext(); + return llvm::cast<SpecificAttr>(*Current); } - static bool classof(const AnnotateAttr *A) { return true; } -}; - -class AsmLabelAttr : public AttrWithString { -public: - AsmLabelAttr(ASTContext &C, llvm::StringRef L) - : AttrWithString(attr::AsmLabel, C, L) {} - - llvm::StringRef getLabel() const { return getString(); } - - virtual Attr* clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::AsmLabel; - } - static bool classof(const AsmLabelAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AlwaysInline); - -class AliasAttr : public AttrWithString { -public: - AliasAttr(ASTContext &C, llvm::StringRef aliasee) - : AttrWithString(attr::Alias, C, aliasee) {} - - llvm::StringRef getAliasee() const { return getString(); } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Alias; } - static bool classof(const AliasAttr *A) { return true; } -}; - -class ConstructorAttr : public Attr { - int priority; -public: - ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {} - - int getPriority() const { return priority; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Constructor; } - static bool classof(const ConstructorAttr *A) { return true; } -}; - -class DestructorAttr : public Attr { - int priority; -public: - DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {} - - int getPriority() const { return priority; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Destructor; } - static bool classof(const DestructorAttr *A) { return true; } -}; - -class IBOutletAttr : public Attr { -public: - IBOutletAttr() : Attr(attr::IBOutlet) {} - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBOutlet; - } - static bool classof(const IBOutletAttr *A) { return true; } -}; - -class IBOutletCollectionAttr : public Attr { - const ObjCInterfaceDecl *D; -public: - IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) - : Attr(attr::IBOutletCollection), D(d) {} - - const ObjCInterfaceDecl *getClass() const { return D; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBOutletCollection; + pointer operator->() const { + AdvanceToNext(); + return llvm::cast<SpecificAttr>(*Current); } - static bool classof(const IBOutletCollectionAttr *A) { return true; } -}; - -class IBActionAttr : public Attr { -public: - IBActionAttr() : Attr(attr::IBAction) {} - - virtual Attr *clone(ASTContext &C) const; - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::IBAction; + specific_attr_iterator& operator++() { + ++Current; + return *this; } - static bool classof(const IBActionAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(AnalyzerNoReturn); -DEF_SIMPLE_ATTR(Deprecated); -DEF_SIMPLE_ATTR(GNUInline); -DEF_SIMPLE_ATTR(Malloc); -DEF_SIMPLE_ATTR(NoReturn); -DEF_SIMPLE_ATTR(NoInstrumentFunction); - -class SectionAttr : public AttrWithString { -public: - SectionAttr(ASTContext &C, llvm::StringRef N) - : AttrWithString(attr::Section, C, N) {} - - llvm::StringRef getName() const { return getString(); } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::Section; + specific_attr_iterator operator++(int) { + specific_attr_iterator Tmp(*this); + ++(*this); + return Tmp; } - static bool classof(const SectionAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(Unavailable); -DEF_SIMPLE_ATTR(Unused); -DEF_SIMPLE_ATTR(Used); -DEF_SIMPLE_ATTR(Weak); -DEF_SIMPLE_ATTR(WeakImport); -DEF_SIMPLE_ATTR(WeakRef); -DEF_SIMPLE_ATTR(NoThrow); -DEF_SIMPLE_ATTR(Const); -DEF_SIMPLE_ATTR(Pure); - -class NonNullAttr : public Attr { - unsigned* ArgNums; - unsigned Size; -public: - NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0); - - virtual void Destroy(ASTContext &C); - - typedef const unsigned *iterator; - iterator begin() const { return ArgNums; } - iterator end() const { return ArgNums + Size; } - unsigned size() const { return Size; } - bool isNonNull(unsigned arg) const { - return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true; + friend bool operator==(specific_attr_iterator Left, + specific_attr_iterator Right) { + if (Left.Current < Right.Current) + Left.AdvanceToNext(Right.Current); + else + Right.AdvanceToNext(Left.Current); + return Left.Current == Right.Current; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; } - static bool classof(const NonNullAttr *A) { return true; } -}; - -class FormatAttr : public AttrWithString { - int formatIdx, firstArg; -public: - FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first) - : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {} - - llvm::StringRef getType() const { return getString(); } - void setType(ASTContext &C, llvm::StringRef type); - int getFormatIdx() const { return formatIdx; } - int getFirstArg() const { return firstArg; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Format; } - static bool classof(const FormatAttr *A) { return true; } -}; - -class FormatArgAttr : public Attr { - int formatIdx; -public: - FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {} - int getFormatIdx() const { return formatIdx; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; } - static bool classof(const FormatArgAttr *A) { return true; } -}; - -class SentinelAttr : public Attr { - int sentinel, NullPos; -public: - SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel), - sentinel(sentinel_val), NullPos(nullPos) {} - int getSentinel() const { return sentinel; } - int getNullPos() const { return NullPos; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; } - static bool classof(const SentinelAttr *A) { return true; } -}; - -class VisibilityAttr : public Attr { -public: - /// @brief An enumeration for the kinds of visibility of symbols. - enum VisibilityTypes { - DefaultVisibility = 0, - HiddenVisibility, - ProtectedVisibility - }; -private: - VisibilityTypes VisibilityType; -public: - VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility), - VisibilityType(v) {} - - VisibilityTypes getVisibility() const { return VisibilityType; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::Visibility; } - static bool classof(const VisibilityAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(FastCall); -DEF_SIMPLE_ATTR(StdCall); -DEF_SIMPLE_ATTR(ThisCall); -DEF_SIMPLE_ATTR(CDecl); -DEF_SIMPLE_ATTR(TransparentUnion); -DEF_SIMPLE_ATTR(ObjCNSObject); -DEF_SIMPLE_ATTR(ObjCException); - -class OverloadableAttr : public Attr { -public: - OverloadableAttr() : Attr(attr::Overloadable) { } - - virtual bool isMerged() const { return false; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) - { return A->getKind() == attr::Overloadable; } - static bool classof(const OverloadableAttr *) { return true; } -}; - -class BlocksAttr : public Attr { -public: - enum BlocksAttrTypes { - ByRef = 0 - }; -private: - BlocksAttrTypes BlocksAttrType; -public: - BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {} - - BlocksAttrTypes getType() const { return BlocksAttrType; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; } - static bool classof(const BlocksAttr *A) { return true; } -}; - -class FunctionDecl; - -class CleanupAttr : public Attr { - FunctionDecl *FD; - -public: - CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {} - - const FunctionDecl *getFunctionDecl() const { return FD; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; } - static bool classof(const CleanupAttr *A) { return true; } -}; - -DEF_SIMPLE_ATTR(NoDebug); -DEF_SIMPLE_ATTR(WarnUnusedResult); -DEF_SIMPLE_ATTR(NoInline); - -class RegparmAttr : public Attr { - unsigned NumParams; - -public: - RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {} - - unsigned getNumParams() const { return NumParams; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; } - static bool classof(const RegparmAttr *A) { return true; } -}; - -class ReqdWorkGroupSizeAttr : public Attr { - unsigned X, Y, Z; -public: - ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z) - : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {} - - unsigned getXDim() const { return X; } - unsigned getYDim() const { return Y; } - unsigned getZDim() const { return Z; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { - return A->getKind() == attr::ReqdWorkGroupSize; + friend bool operator!=(specific_attr_iterator Left, + specific_attr_iterator Right) { + return !(Left == Right); } - static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; } }; -class InitPriorityAttr : public Attr { - unsigned Priority; -public: - InitPriorityAttr(unsigned priority) - : Attr(attr::InitPriority), Priority(priority) {} - - virtual void Destroy(ASTContext &C) { Attr::Destroy(C); } - - unsigned getPriority() const { return Priority; } - - virtual Attr *clone(ASTContext &C) const; - - static bool classof(const Attr *A) - { return A->getKind() == attr::InitPriority; } - static bool classof(const InitPriorityAttr *A) { return true; } -}; - -// Checker-specific attributes. -DEF_SIMPLE_ATTR(CFReturnsNotRetained); -DEF_SIMPLE_ATTR(CFReturnsRetained); -DEF_SIMPLE_ATTR(NSReturnsNotRetained); -DEF_SIMPLE_ATTR(NSReturnsRetained); - -// Target-specific attributes -DEF_SIMPLE_ATTR(DLLImport); -DEF_SIMPLE_ATTR(DLLExport); - -class MSP430InterruptAttr : public Attr { - unsigned Number; - -public: - MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {} - - unsigned getNumber() const { return Number; } - - virtual Attr *clone(ASTContext &C) const; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) - { return A->getKind() == attr::MSP430Interrupt; } - static bool classof(const MSP430InterruptAttr *A) { return true; } -}; +template <typename T> +inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) { + return specific_attr_iterator<T>(vec.begin()); +} +template <typename T> +inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) { + return specific_attr_iterator<T>(vec.end()); +} -DEF_SIMPLE_ATTR(X86ForceAlignArgPointer); +template <typename T> +inline bool hasSpecificAttr(const AttrVec& vec) { + return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec); +} +template <typename T> +inline T *getSpecificAttr(const AttrVec& vec) { + specific_attr_iterator<T> i = specific_attr_begin<T>(vec); + if (i != specific_attr_end<T>(vec)) + return *i; + else + return 0; +} -#undef DEF_SIMPLE_ATTR +/// getMaxAlignment - Returns the highest alignment value found among +/// AlignedAttrs in an AttrVec, or 0 if there are none. +inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) { + unsigned Align = 0; + specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end()); + for(; i != e; ++i) + Align = std::max(Align, i->getAlignment(Ctx)); + return Align; +} } // end namespace clang diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 3b09071..800c583 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -5,6 +5,12 @@ tablegen(Attrs.inc add_custom_target(ClangAttrClasses DEPENDS Attrs.inc) +tablegen(AttrImpl.inc + -gen-clang-attr-impl + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrImpl + DEPENDS AttrImpl.inc) + set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) tablegen(StmtNodes.inc -gen-clang-stmt-nodes) diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 9f97fd8..dad4dfc 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -273,6 +273,9 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) @@ -700,9 +703,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const { template<typename T> CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { CanQual<T> Result; - Result.Stored.setFromOpaqueValue(Ptr); - assert((!Result || Result.Stored.isCanonical()) - && "Type is not canonical!"); + Result.Stored = QualType::getFromOpaquePtr(Ptr); + assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || + Result.Stored.isCanonical()) && "Type is not canonical!"); return Result; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 39cd51f..6749255 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -118,16 +118,6 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } - /// getNameAsCString - Get the name of identifier for this declaration as a - /// C string (const char*). This requires that the declaration have a name - /// and that it be a simple identifier. - // - // FIXME: Deprecated, move clients to getName(). - const char *getNameAsCString() const { - assert(Name.isIdentifier() && "Name is not a simple identifier"); - return getIdentifier() ? getIdentifier()->getNameStart() : ""; - } - /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string @@ -229,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { + bool IsInline : 1; + SourceLocation LBracLoc, RBracLoc; // For extended namespace definitions: @@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // there will be one NamespaceDecl for each declaration. // NextNamespace points to the next extended declaration. // OrigNamespace points to the original namespace declaration. - // OrigNamespace of the first namespace decl points to itself. + // OrigNamespace of the first namespace decl points to its anonymous namespace NamespaceDecl *NextNamespace; /// \brief A pointer to either the original namespace definition for @@ -258,28 +250,36 @@ class NamespaceDecl : public NamedDecl, public DeclContext { NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - NextNamespace(0), OrigOrAnonNamespace(0, true) { } + IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - virtual void Destroy(ASTContext& C); - - // \brief Returns true if this is an anonymous namespace declaration. - // - // For example: + /// \brief Returns true if this is an anonymous namespace declaration. + /// + /// For example: /// \code - // namespace { - // ... - // }; - // \endcode - // q.v. C++ [namespace.unnamed] + /// namespace { + /// ... + /// }; + /// \endcode + /// q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } - /// \brief Return the next extended namespace declaration or null if this + /// \brief Returns true if this is an inline namespace declaration. + bool isInline() const { + return IsInline; + } + + /// \brief Set whether this is an inline namespace declaration. + void setInline(bool Inline) { + IsInline = Inline; + } + + /// \brief Return the next extended namespace declaration or null if there /// is none. NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } @@ -345,8 +345,8 @@ public: return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// ValueDecl - Represent the declaration of a variable (in which case it is @@ -392,8 +392,6 @@ struct QualifierInfo { unsigned NumTPLists, TemplateParameterList **TPLists); - void Destroy(ASTContext &Context); - private: // Copy constructor and copy assignment are disabled. QualifierInfo(const QualifierInfo&); @@ -421,9 +419,6 @@ protected: : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} public: - virtual ~DeclaratorDecl(); - virtual void Destroy(ASTContext &C); - TypeSourceInfo *getTypeSourceInfo() const { return hasExtInfo() ? getExtInfo()->TInfo @@ -507,36 +502,11 @@ struct EvaluatedStmt { APValue Evaluated; }; -// \brief Describes the kind of template specialization that a -// particular template specialization declaration represents. -enum TemplateSpecializationKind { - /// This template specialization was formed from a template-id but - /// has not yet been declared, defined, or instantiated. - TSK_Undeclared = 0, - /// This template specialization was implicitly instantiated from a - /// template. (C++ [temp.inst]). - TSK_ImplicitInstantiation, - /// This template specialization was declared or defined by an - /// explicit specialization (C++ [temp.expl.spec]) or partial - /// specialization (C++ [temp.class.spec]). - TSK_ExplicitSpecialization, - /// This template specialization was instantiated from a template - /// due to an explicit instantiation declaration request - /// (C++0x [temp.explicit]). - TSK_ExplicitInstantiationDeclaration, - /// This template specialization was instantiated from a template - /// due to an explicit instantiation definition request - /// (C++ [temp.explicit]). - TSK_ExplicitInstantiationDefinition -}; - /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - enum StorageClass { - None, Auto, Register, Extern, Static, PrivateExtern - }; + typedef clang::StorageClass StorageClass; /// getStorageClassSpecifierString - Return the string used to /// specify the storage class \arg SC. @@ -568,10 +538,6 @@ private: bool ThreadSpecified : 1; bool HasCXXDirectInit : 1; - /// DeclaredInCondition - Whether this variable was declared in a - /// condition, e.g., if (int x = foo()) { ... }. - bool DeclaredInCondition : 1; - /// \brief Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. bool ExceptionVar : 1; @@ -587,7 +553,7 @@ protected: StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { + ExceptionVar(false), NRVOVariable(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -609,9 +575,6 @@ public: QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten); - virtual void Destroy(ASTContext& C); - virtual ~VarDecl(); - virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; @@ -619,8 +582,14 @@ public: StorageClass getStorageClassAsWritten() const { return (StorageClass) SClassAsWritten; } - void setStorageClass(StorageClass SC) { SClass = SC; } - void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + void setStorageClass(StorageClass SC) { + assert(isLegalForVariable(SC)); + SClass = SC; + } + void setStorageClassAsWritten(StorageClass SC) { + assert(isLegalForVariable(SC)); + SClassAsWritten = SC; + } void setThreadSpecified(bool T) { ThreadSpecified = T; } bool isThreadSpecified() const { @@ -630,25 +599,26 @@ public: /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. bool hasLocalStorage() const { - if (getStorageClass() == None) + if (getStorageClass() == SC_None) return !isFileVarDecl(); // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern. - return getStorageClass() <= Register; + return getStorageClass() >= SC_Auto; } /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { - return getStorageClass() == Static && !isFileVarDecl(); + return getStorageClass() == SC_Static && !isFileVarDecl(); } /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { - return getStorageClass() == Extern || getStorageClass() == PrivateExtern; + return getStorageClass() == SC_Extern || + getStorageClass() == SC_PrivateExtern; } /// hasGlobalStorage - Returns true for all variables that do not @@ -670,7 +640,7 @@ public: if (getKind() != Decl::Var) return false; if (const DeclContext *DC = getDeclContext()) - return DC->getLookupContext()->isFunctionOrMethod(); + return DC->getRedeclContext()->isFunctionOrMethod(); return false; } @@ -679,10 +649,8 @@ public: bool isFunctionOrMethodVarDecl() const { if (getKind() != Decl::Var) return false; - if (const DeclContext *DC = getDeclContext()) - return DC->getLookupContext()->isFunctionOrMethod() && - DC->getLookupContext()->getDeclKind() != Decl::Block; - return false; + const DeclContext *DC = getDeclContext()->getRedeclContext(); + return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block; } /// \brief Determines whether this is a static data member. @@ -696,7 +664,7 @@ public: /// \endcode bool isStaticDataMember() const { // If it wasn't static, it would be a FieldDecl. - return getDeclContext()->isRecord(); + return getKind() != Decl::ParmVar && getDeclContext()->isRecord(); } virtual VarDecl *getCanonicalDecl(); @@ -743,11 +711,10 @@ public: bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; - if (const DeclContext *Ctx = getDeclContext()) { - Ctx = Ctx->getLookupContext(); - if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) - return true; - } + + if (getDeclContext()->getRedeclContext()->isFileContext()) + return true; + if (isStaticDataMember()) return true; @@ -912,18 +879,6 @@ public: return HasCXXDirectInit; } - /// isDeclaredInCondition - Whether this variable was declared as - /// part of a condition in an if/switch/while statement, e.g., - /// @code - /// if (int x = foo()) { ... } - /// @endcode - bool isDeclaredInCondition() const { - return DeclaredInCondition; - } - void setDeclaredInCondition(bool InCondition) { - DeclaredInCondition = InCondition; - } - /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C @catch statement. bool isExceptionVariable() const { @@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -1117,9 +1072,7 @@ public: class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: - enum StorageClass { - None, Extern, Static, PrivateExtern - }; + typedef clang::StorageClass StorageClass; /// \brief The kind of templated function a FunctionDecl can be. enum TemplatedKind { @@ -1179,11 +1132,15 @@ private: DependentFunctionTemplateSpecializationInfo *> TemplateOrSpecialization; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the DeclaratorDecl base class. + DeclarationNameLoc DNLoc; + protected: - FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, bool isInline) - : DeclaratorDecl(DK, DC, L, N, T, TInfo), + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), DeclContext(DK), ParamInfo(0), Body(), SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), @@ -1191,10 +1148,9 @@ protected: HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsCopyAssignment(false), HasImplicitReturnZero(false), - EndRangeLoc(L), TemplateOrSpecialization() {} - - virtual ~FunctionDecl() {} - virtual void Destroy(ASTContext& C); + EndRangeLoc(NameInfo.getEndLoc()), + TemplateOrSpecialization(), + DNLoc(NameInfo.getInfo()) {} typedef Redeclarable<FunctionDecl> redeclarable_base; virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } @@ -1211,11 +1167,27 @@ public: static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = None, - StorageClass SCAsWritten = None, + StorageClass S = SC_None, + StorageClass SCAsWritten = SC_None, + bool isInline = false, + bool hasWrittenPrototype = true) { + DeclarationNameInfo NameInfo(N, L); + return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, + isInline, hasWrittenPrototype); + } + + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + StorageClass S = SC_None, + StorageClass SCAsWritten = SC_None, bool isInline = false, bool hasWrittenPrototype = true); + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; @@ -1245,7 +1217,7 @@ public: /// set that function declaration to the actual declaration /// containing the body (if there is one). /// NOTE: For checking if there is a body, use hasBody() instead, to avoid - /// unnecessary PCH de-serialization of the body. + /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; virtual Stmt *getBody() const { @@ -1389,12 +1361,18 @@ public: } StorageClass getStorageClass() const { return StorageClass(SClass); } - void setStorageClass(StorageClass SC) { SClass = SC; } + void setStorageClass(StorageClass SC) { + assert(isLegalForFunction(SC)); + SClass = SC; + } StorageClass getStorageClassAsWritten() const { return StorageClass(SClassAsWritten); } - void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + void setStorageClassAsWritten(StorageClass SC) { + assert(isLegalForFunction(SC)); + SClassAsWritten = SC; + } /// \brief Determine whether the "inline" keyword was specified for this /// function. @@ -1632,8 +1610,8 @@ public: return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; @@ -1705,7 +1683,6 @@ protected: const llvm::APSInt &V) : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} - virtual ~EnumConstantDecl() {} public: static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, @@ -1713,8 +1690,6 @@ public: QualType T, Expr *E, const llvm::APSInt &V); - virtual void Destroy(ASTContext& C); - const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } const llvm::APSInt &getInitVal() const { return Val; } @@ -1722,6 +1697,8 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumConstantDecl *D) { return true; } @@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - virtual ~TypedefDecl(); - protected: typedef Redeclarable<TypedefDecl> redeclarable_base; virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } @@ -1832,6 +1807,9 @@ private: /// it is a declaration ("struct foo;"). bool IsDefinition : 1; + /// IsBeingDefined - True if this is currently being defined. + bool IsBeingDefined : 1; + /// IsEmbeddedInDeclarator - True if this tag declaration is /// "embedded" (i.e., defined or declared for the very first time) /// in the syntax of a declarator. @@ -1873,6 +1851,7 @@ protected: "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; IsDefinition = false; + IsBeingDefined = false; IsEmbeddedInDeclarator = false; setPreviousDeclaration(PrevDecl); } @@ -1881,8 +1860,6 @@ protected: virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } public: - void Destroy(ASTContext &C); - typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { return redeclarable_base::redecls_begin(); @@ -1911,11 +1888,22 @@ public: return const_cast<TagDecl*>(this)->getCanonicalDecl(); } + /// isThisDeclarationADefinition() - Return true if this declaration + /// defines the type. Provided for consistency. + bool isThisDeclarationADefinition() const { + return isDefinition(); + } + /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { return IsDefinition; } + /// isBeingDefined - Return true if this decl is currently being defined. + bool isBeingDefined() const { + return IsBeingDefined; + } + bool isEmbeddedInDeclarator() const { return IsEmbeddedInDeclarator; } @@ -2003,8 +1991,8 @@ public: return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// EnumDecl - Represents an enum. As an extension, we allow forward-declared @@ -2037,6 +2025,8 @@ class EnumDecl : public TagDecl { IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); + NumNegativeBits = 0; + NumPositiveBits = 0; } public: EnumDecl *getCanonicalDecl() { @@ -2058,8 +2048,6 @@ public: SourceLocation TKL, EnumDecl *PrevDecl); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - /// completeDefinition - When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the /// declaration as being defined; it's enumerators have already been @@ -2167,7 +2155,6 @@ protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, RecordDecl *PrevDecl, SourceLocation TKL); - virtual ~RecordDecl(); public: static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, @@ -2183,8 +2170,6 @@ public: return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); } - virtual void Destroy(ASTContext& C); - bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } @@ -2307,9 +2292,6 @@ protected: IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), SignatureAsWritten(0) {} - virtual ~BlockDecl(); - virtual void Destroy(ASTContext& C); - public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index be30b8e..1369c2b 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -222,11 +222,13 @@ protected: // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum unsigned Access : 2; friend class CXXClassMemberWrapper; - - // PCHLevel - the "level" of precompiled header/AST file from which this - // declaration was built. - unsigned PCHLevel : 3; - + + /// PCHLevel - the "level" of AST file from which this declaration was built. + unsigned PCHLevel : 2; + + /// ChangedAfterLoad - if this declaration has changed since being loaded + bool ChangedAfterLoad : 1; + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 15; @@ -243,7 +245,7 @@ protected: : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), - Access(AS_none), PCHLevel(0), + Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { if (Decl::CollectingStats()) add(DK); } @@ -251,7 +253,7 @@ protected: Decl(Kind DK, EmptyShell Empty) : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), - Access(AS_none), PCHLevel(0), + Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { if (Decl::CollectingStats()) add(DK); } @@ -305,24 +307,52 @@ public: } bool hasAttrs() const { return HasAttrs; } - void initAttrs(Attr *attrs); - void addAttr(Attr *attr); - const Attr *getAttrs() const { - if (!HasAttrs) return 0; // common case, no attributes. - return getAttrsImpl(); // Uncommon case, out of line hash lookup. + void setAttrs(const AttrVec& Attrs); + AttrVec& getAttrs() { + return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } + const AttrVec &getAttrs() const; void swapAttrs(Decl *D); - void invalidateAttrs(); + void dropAttrs(); + + void addAttr(Attr *A) { + if (hasAttrs()) + getAttrs().push_back(A); + else + setAttrs(AttrVec(1, A)); + } + + typedef AttrVec::const_iterator attr_iterator; + + // FIXME: Do not rely on iterators having comparable singular values. + // Note that this should error out if they do not. + attr_iterator attr_begin() const { + return hasAttrs() ? getAttrs().begin() : 0; + } + attr_iterator attr_end() const { + return hasAttrs() ? getAttrs().end() : 0; + } - template<typename T> const T *getAttr() const { - for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) - if (const T *V = dyn_cast<T>(attr)) - return V; - return 0; + template <typename T> + specific_attr_iterator<T> specific_attr_begin() const { + return specific_attr_iterator<T>(attr_begin()); + } + template <typename T> + specific_attr_iterator<T> specific_attr_end() const { + return specific_attr_iterator<T>(attr_end()); } + template<typename T> T *getAttr() const { + return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0; + } template<typename T> bool hasAttr() const { - return getAttr<T>() != 0; + return hasAttrs() && hasSpecificAttr<T>(getAttrs()); + } + + /// getMaxAlignment - return the maximum alignment specified by attributes + /// on this decl, 0 if there are none. + unsigned getMaxAlignment() const { + return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0; } /// setInvalidDecl - Indicates the Decl had a semantic error. This @@ -343,22 +373,21 @@ public: /// (in addition to the "used" bit set by \c setUsed()) when determining /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - + void setUsed(bool U = true) { Used = U; } /// \brief Retrieve the level of precompiled header from which this /// declaration was generated. /// /// The PCH level of a declaration describes where the declaration originated - /// from. A PCH level of 0 indicates that the declaration was not from a - /// precompiled header. A PCH level of 1 indicates that the declaration was - /// from a top-level precompiled header; 2 indicates that the declaration - /// comes from a precompiled header on which the top-level precompiled header - /// depends, and so on. + /// from. A PCH level of 0 indicates that the declaration was parsed from + /// source. A PCH level of 1 indicates that the declaration was loaded from + /// a top-level AST file. A PCH level 2 indicates that the declaration was + /// loaded from a PCH file the AST file depends on, and so on. unsigned getPCHLevel() const { return PCHLevel; } /// \brief The maximum PCH level that any declaration may have. - static const unsigned MaxPCHLevel = 7; + static const unsigned MaxPCHLevel = 3; /// \brief Set the PCH level of this declaration. void setPCHLevel(unsigned Level) { @@ -366,6 +395,19 @@ public: PCHLevel = Level; } + /// \brief Query whether this declaration was changed in a significant way + /// since being loaded from an AST file. + /// + /// In an epic violation of layering, what is "significant" is entirely + /// up to the serialization system, but implemented in AST and Sema. + bool isChangedSinceDeserialization() const { return ChangedAfterLoad; } + + /// \brief Mark this declaration as having changed since deserialization, or + /// reset the flag. + void setChangedSinceDeserialization(bool Changed) { + ChangedAfterLoad = Changed; + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -411,10 +453,10 @@ public: void setLexicalDeclContext(DeclContext *DC); - // isDefinedOutsideFunctionOrMethod - This predicate returns true if this - // scoped decl is defined outside the current function or method. This is - // roughly global variables and functions, but also handles enums (which could - // be defined inside or outside a function etc). + /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this + /// scoped decl is defined outside the current function or method. This is + /// roughly global variables and functions, but also handles enums (which + /// could be defined inside or outside a function etc). bool isDefinedOutsideFunctionOrMethod() const; /// \brief Retrieves the "canonical" declaration of the given declaration. @@ -572,9 +614,6 @@ public: static DeclContext *castToDeclContext(const Decl *); static Decl *castFromDeclContext(const DeclContext *); - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const; void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0) const; @@ -603,6 +642,29 @@ public: virtual void print(llvm::raw_ostream &OS) const; }; +class DeclContextLookupResult + : public std::pair<NamedDecl**,NamedDecl**> { +public: + DeclContextLookupResult(NamedDecl **I, NamedDecl **E) + : std::pair<NamedDecl**,NamedDecl**>(I, E) {} + DeclContextLookupResult() + : std::pair<NamedDecl**,NamedDecl**>() {} + + using std::pair<NamedDecl**,NamedDecl**>::operator=; +}; + +class DeclContextLookupConstResult + : public std::pair<NamedDecl*const*, NamedDecl*const*> { +public: + DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R) + : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {} + DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E) + : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {} + DeclContextLookupConstResult() + : std::pair<NamedDecl*const*, NamedDecl*const*>() {} + + using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=; +}; /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes @@ -654,8 +716,6 @@ protected: ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), LastDecl(0) { } - void DestroyDecls(ASTContext &C); - public: ~DeclContext(); @@ -724,6 +784,8 @@ public: return DeclKind == Decl::Namespace; } + bool isInlineNamespace() const; + /// \brief Determines whether this context is dependent on a /// template parameter. bool isDependentContext() const; @@ -742,19 +804,18 @@ public: /// Here, E is a transparent context, so its enumerator (Val1) will /// appear (semantically) that it is in the same context of E. /// Examples of transparent contexts include: enumerations (except for - /// C++0x scoped enums), C++ linkage specifications, and C++0x - /// inline namespaces. + /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. - bool Equals(DeclContext *DC) { + bool Equals(const DeclContext *DC) const { return DC && this->getPrimaryContext() == DC->getPrimaryContext(); } /// \brief Determine whether this declaration context encloses the /// declaration context DC. - bool Encloses(DeclContext *DC); + bool Encloses(const DeclContext *DC) const; /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations @@ -767,13 +828,12 @@ public: return const_cast<DeclContext*>(this)->getPrimaryContext(); } - /// getLookupContext - Retrieve the innermost non-transparent - /// context of this context, which corresponds to the innermost - /// location from which name lookup can find the entities in this - /// context. - DeclContext *getLookupContext(); - const DeclContext *getLookupContext() const { - return const_cast<DeclContext *>(this)->getLookupContext(); + /// getRedeclContext - Retrieve the context in which an entity conflicts with + /// other entities of the same name, or where it is a redeclaration if the + /// two entities are compatible. This skips through transparent contexts. + DeclContext *getRedeclContext(); + const DeclContext *getRedeclContext() const { + return const_cast<DeclContext *>(this)->getRedeclContext(); } /// \brief Retrieve the nearest enclosing namespace context. @@ -782,6 +842,14 @@ public: return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); } + /// \brief Test if this context is part of the enclosing namespace set of + /// the context NS, as defined in C++0x [namespace.def]p9. If either context + /// isn't a namespace, this is equivalent to Equals(). + /// + /// The enclosing namespace set of a namespace is the namespace and, if it is + /// inline, its enclosing namespace, recursively. + bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; + /// getNextContext - If this is a DeclContext that may have other /// DeclContexts that are semantically connected but syntactically /// different, such as C++ namespaces, this routine retrieves the @@ -845,6 +913,12 @@ public: decl_iterator decls_end() const; bool decls_empty() const; + /// noload_decls_begin/end - Iterate over the declarations stored in this + /// context that are currently loaded; don't attempt to retrieve anything + /// from an external source. + decl_iterator noload_decls_begin() const; + decl_iterator noload_decls_end() const; + /// specific_decl_iterator - Iterates over a subrange of /// declarations stored in a DeclContext, providing only those that /// are of type SpecificDecl (or a class derived from it). This @@ -1020,9 +1094,8 @@ public: /// access to the results of lookup up a name within this context. typedef NamedDecl * const * lookup_const_iterator; - typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; - typedef std::pair<lookup_const_iterator, lookup_const_iterator> - lookup_const_result; + typedef DeclContextLookupResult lookup_result; + typedef DeclContextLookupConstResult lookup_const_result; /// lookup - Find the declarations (if any) with the given Name in /// this context. Returns a range of iterators that contains all of @@ -1052,6 +1125,14 @@ public: /// the declaration chains. void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); + /// \brief Deserialize all the visible declarations from external storage. + /// + /// Name lookup deserializes visible declarations lazily, thus a DeclContext + /// may not have a complete name lookup table. This function deserializes + /// the rest of visible declarations from the external storage and completes + /// the name lookup table. + void MaterializeVisibleDeclsFromExternalStorage(); + /// udir_iterator - Iterates through the using-directives stored /// within this context. typedef UsingDirectiveDecl * const * udir_iterator; @@ -1109,7 +1190,6 @@ public: private: void LoadLexicalDeclsFromExternalStorage() const; - void LoadVisibleDeclsFromExternalStorage() const; friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; @@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const { getKind() == TemplateTemplateParm; } - // Specialization selected when ToTy is not a known subclass of DeclContext. template <class ToTy, bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 41474ab..a9802bf 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -17,6 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Decl.h" +#include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -159,7 +160,6 @@ 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. @@ -177,15 +177,17 @@ class CXXBaseSpecifier { /// 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; + /// BaseTypeInfo - The type of the base class. This will be a class or struct + /// (or a typedef of such). The source code range does not include the + /// "virtual" or access specifier. + TypeSourceInfo *BaseTypeInfo; public: CXXBaseSpecifier() { } - CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T) - : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { } + CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, + TypeSourceInfo *TInfo) + : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { } /// getSourceRange - Retrieves the source range that contains the /// entire base specifier. @@ -195,7 +197,7 @@ public: /// class (or not). bool isVirtual() const { return Virtual; } - /// \brief Determine whether this base class if a base of a class declared + /// \brief Determine whether this base class is a base of a class declared /// with the 'class' keyword (vs. one declared with the 'struct' keyword). bool isBaseOfClass() const { return BaseOfClass; } @@ -221,7 +223,10 @@ public: /// getType - Retrieves the type of the base class. This type will /// always be an unqualified class type. - QualType getType() const { return BaseType; } + QualType getType() const { return BaseTypeInfo->getType(); } + + /// getTypeLoc - Retrieves the type and source location of the base class. + TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; /// CXXRecordDecl - Represents a C++ struct/union/class. @@ -400,8 +405,6 @@ protected: CXXRecordDecl *PrevDecl, SourceLocation TKL = SourceLocation()); - ~CXXRecordDecl(); - public: /// base_class_iterator - Iterator that traverses the base classes /// of a class. @@ -449,8 +452,6 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; } @@ -1056,29 +1057,30 @@ public: return true; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// 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, + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isStatic, StorageClass SCAsWritten, bool isInline) - : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), + : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_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); + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + bool isStatic = false, + StorageClass SCAsWritten = SC_None, + bool isInline = false); - bool isStatic() const { return getStorageClass() == Static; } + bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } bool isVirtual() const { @@ -1249,9 +1251,6 @@ public: 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*>(); } @@ -1285,7 +1284,7 @@ public: /// getMember - If this is a member initializer, returns the /// declaration of the non-static data member being /// initialized. Otherwise, returns NULL. - FieldDecl *getMember() { + FieldDecl *getMember() const { if (isMemberInitializer()) return BaseOrMember.get<FieldDecl*>(); else @@ -1363,7 +1362,7 @@ public: reinterpret_cast<VarDecl **>(this + 1)[I] = Index; } - Expr *getInit() { return static_cast<Expr *>(Init); } + Expr *getInit() const { return static_cast<Expr *>(Init); } }; /// CXXConstructorDecl - Represents a C++ constructor within a @@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXBaseOrMemberInitializer **BaseOrMemberInitializers; unsigned NumBaseOrMemberInitializers; - CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, - FunctionDecl::None, isInline), + : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, + SC_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, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared); @@ -1519,8 +1517,8 @@ public: static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// CXXDestructorDecl - Represents a C++ destructor within a @@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl { 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), + CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false, + SC_None, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl { public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, + const DeclarationNameInfo &NameInfo, QualType T, bool isInline, bool isImplicitlyDeclared); @@ -1585,8 +1582,8 @@ public: static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// CXXConversionDecl - Represents a C++ conversion function within a @@ -1604,17 +1601,17 @@ class CXXConversionDecl : public CXXMethodDecl { /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo, + CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, - FunctionDecl::None, isInline), + : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false, + SC_None, isInline), IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation L, DeclarationName N, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit); @@ -1642,8 +1639,8 @@ public: static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// LinkageSpecDecl - This represents a linkage specification. For example: @@ -1710,7 +1707,9 @@ public: // artificial name, for all using-directives in order to store // them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { - + /// \brief The location of the "using" keyword. + SourceLocation UsingLoc; + /// SourceLocation - Location of 'namespace' token. SourceLocation NamespaceLoc; @@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl { /// 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; @@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl { return DeclarationName::getUsingDirectiveName(); } - UsingDirectiveDecl(DeclContext *DC, SourceLocation L, + UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespcLoc, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor) - : NamedDecl(UsingDirective, DC, L, getName()), + : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), - Qualifier(Qualifier), IdentLoc(IdentLoc), - NominatedNamespace(Nominated), + Qualifier(Qualifier), NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } @@ -1759,18 +1753,10 @@ public: /// 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; @@ -1783,34 +1769,23 @@ public: 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; } - + /// \brief Return the location of the "using" keyword. + SourceLocation getUsingLoc() const { return UsingLoc; } + // 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; } + SourceLocation getIdentLocation() const { return getLocation(); } static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, + SourceLocation UsingLoc, SourceLocation NamespaceLoc, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, @@ -1818,12 +1793,18 @@ public: NamedDecl *Nominated, DeclContext *CommonAncestor); + SourceRange getSourceRange() const { + return SourceRange(UsingLoc, getLocation()); + } + 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 == UsingDirective; } // Friend for getUsingDirectiveName. friend class DeclContext; + + friend class ASTDeclReader; }; /// NamespaceAliasDecl - Represents a C++ namespace alias. For example: @@ -1832,7 +1813,8 @@ public: /// namespace Foo = Bar; /// @endcode class NamespaceAliasDecl : public NamedDecl { - SourceLocation AliasLoc; + /// \brief The location of the "namespace" keyword. + SourceLocation NamespaceLoc; /// \brief The source range that covers the nested-name-specifier /// preceding the namespace name. @@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl { /// NamespaceDecl or a NamespaceAliasDecl. NamedDecl *Namespace; - NamespaceAliasDecl(DeclContext *DC, SourceLocation L, + NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), - QualifierRange(QualifierRange), Qualifier(Qualifier), - IdentLoc(IdentLoc), Namespace(Namespace) { } + : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), + NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange), + Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { } + friend class ASTDeclReader; + public: /// \brief Retrieve the source range of the nested-name-specifier /// that qualifiers the namespace name. @@ -1889,41 +1873,31 @@ public: /// 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; } + SourceLocation getAliasLoc() const { return getLocation(); } /// Returns the location of the 'namespace' keyword. - SourceLocation getNamespaceLoc() const { return getLocation(); } + SourceLocation getNamespaceLoc() const { return NamespaceLoc; } /// 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, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace); + virtual SourceRange getSourceRange() const { + return SourceRange(NamespaceLoc, IdentLoc); + } + 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 == NamespaceAlias; } @@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl { /// \brief Target nested name specifier. NestedNameSpecifier* TargetNestedName; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + /// \brief The collection of shadow declarations associated with /// this using declaration. This set can change as a class is /// processed. @@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl { // \brief Has 'typename' keyword. bool IsTypeName; - UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, + UsingDecl(DeclContext *DC, SourceRange NNR, SourceLocation UL, NestedNameSpecifier* TargetNNS, - DeclarationName Name, bool IsTypeNameArg) - : NamedDecl(Using, DC, L, Name), + const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) + : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), - IsTypeName(IsTypeNameArg) { + DNLoc(NameInfo.getInfo()), 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; } + SourceRange getNestedNameRange() const { 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; } + SourceLocation getUsingLocation() const { 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() { + NestedNameSpecifier* getTargetNestedNameDecl() const { return TargetNestedName; } @@ -2046,6 +2021,10 @@ public: TargetNestedName = NNS; } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + /// \brief Return true if the using declaration has 'typename'. bool isTypeName() const { return IsTypeName; } @@ -2076,15 +2055,21 @@ public: } static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, - NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); + SourceRange NNR, SourceLocation UsingL, + NestedNameSpecifier* TargetNNS, + const DeclarationNameInfo &NameInfo, + bool IsTypeNameArg); + + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getNameInfo().getEndLoc()); + } 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 == Using; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// UnresolvedUsingValueDecl - Represents a dependent using @@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl { NestedNameSpecifier *TargetNestedNameSpecifier; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, - DeclarationName TargetName) - : ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TargetNestedNameSpecifier(TargetNNS) + const DeclarationNameInfo &NameInfo) + : ValueDecl(UnresolvedUsingValue, DC, + NameInfo.getLoc(), NameInfo.getName(), Ty), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo()) { } public: @@ -2125,7 +2114,7 @@ public: void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() { + NestedNameSpecifier* getTargetNestedNameSpecifier() const { return TargetNestedNameSpecifier; } @@ -2140,10 +2129,18 @@ public: /// \brief Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, DeclarationName TargetName); + const DeclarationNameInfo &NameInfo); + + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getNameInfo().getEndLoc()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingValueDecl *D) { return true; } @@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) { } + friend class ASTDeclReader; + 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); + SourceRange getSourceRange() const { + return SourceRange(UsingLocation, getLocation()); + } + 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 == UnresolvedUsingTypename; } @@ -2243,12 +2231,11 @@ public: 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 == StaticAssert; } + + friend class ASTDeclReader; }; /// Insertion operator for diagnostics. This allows sending AccessSpecifier's diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 9602b67..97da6ca 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -29,108 +29,54 @@ class DependentDiagnostic; /// StoredDeclsList - This is an array of decls optimized a common case of only /// containing one entry. struct StoredDeclsList { - /// The kind of data encoded in this list. - enum DataKind { - /// \brief The data is a NamedDecl*. - DK_Decl = 0, - /// \brief The data is a declaration ID (an unsigned value), - /// shifted left by 2 bits. - DK_DeclID = 1, - /// \brief The data is a pointer to a vector (of type VectorTy) - /// that contains declarations. - DK_Decl_Vector = 2, - /// \brief The data is a pointer to a vector (of type VectorTy) - /// that contains declaration ID. - DK_ID_Vector = 3 - }; - - /// VectorTy - When in vector form, this is what the Data pointer points to. - typedef llvm::SmallVector<uintptr_t, 4> VectorTy; - - /// \brief The stored data, which will be either a declaration ID, a - /// pointer to a NamedDecl, or a pointer to a vector. - uintptr_t Data; + + /// DeclsTy - When in vector form, this is what the Data pointer points to. + typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy; + + /// \brief The stored data, which will be either a pointer to a NamedDecl, + /// or a pointer to a vector. + llvm::PointerUnion<NamedDecl *, DeclsTy *> Data; public: - StoredDeclsList() : Data(0) {} + StoredDeclsList() {} StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { - if (VectorTy *RHSVec = RHS.getAsVector()) { - VectorTy *New = new VectorTy(*RHSVec); - Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); - } + if (DeclsTy *RHSVec = RHS.getAsVector()) + Data = new DeclsTy(*RHSVec); } ~StoredDeclsList() { // If this is a vector-form, free the vector. - if (VectorTy *Vector = getAsVector()) + if (DeclsTy *Vector = getAsVector()) delete Vector; } StoredDeclsList &operator=(const StoredDeclsList &RHS) { - if (VectorTy *Vector = getAsVector()) + if (DeclsTy *Vector = getAsVector()) delete Vector; Data = RHS.Data; - if (VectorTy *RHSVec = RHS.getAsVector()) { - VectorTy *New = new VectorTy(*RHSVec); - Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); - } + if (DeclsTy *RHSVec = RHS.getAsVector()) + Data = new DeclsTy(*RHSVec); return *this; } - bool isNull() const { return (Data & ~0x03) == 0; } + bool isNull() const { return Data.isNull(); } NamedDecl *getAsDecl() const { - if ((Data & 0x03) != DK_Decl) - return 0; - - return reinterpret_cast<NamedDecl *>(Data & ~0x03); + return Data.dyn_cast<NamedDecl *>(); } - VectorTy *getAsVector() const { - if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) - return 0; - - return reinterpret_cast<VectorTy *>(Data & ~0x03); + DeclsTy *getAsVector() const { + return Data.dyn_cast<DeclsTy *>(); } void setOnlyValue(NamedDecl *ND) { assert(!getAsVector() && "Not inline"); - Data = reinterpret_cast<uintptr_t>(ND); - } - - void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { - if (Vec.size() > 1) { - VectorTy *Vector = getAsVector(); - if (!Vector) { - Vector = new VectorTy; - Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector; - } - - Vector->resize(Vec.size()); - std::copy(Vec.begin(), Vec.end(), Vector->begin()); - return; - } - - if (VectorTy *Vector = getAsVector()) - delete Vector; - - if (Vec.empty()) - Data = 0; - else - Data = (Vec[0] << 2) | DK_DeclID; - } - - /// \brief Force the stored declarations list to contain actual - /// declarations. - /// - /// This routine will resolve any declaration IDs for declarations - /// that may not yet have been loaded from external storage. - void materializeDecls(ASTContext &Context); - - bool hasDeclarationIDs() const { - DataKind DK = (DataKind)(Data & 0x03); - return DK == DK_DeclID || DK == DK_ID_Vector; + Data = ND; + // Make sure that Data is a plain NamedDecl* so we can use its address + // at getLookupResult. + assert(*(NamedDecl **)&Data == ND && + "PointerUnion mangles the NamedDecl pointer!"); } void remove(NamedDecl *D) { @@ -138,30 +84,26 @@ public: if (NamedDecl *Singleton = getAsDecl()) { assert(Singleton == D && "list is different singleton"); (void)Singleton; - Data = 0; + Data = (NamedDecl *)0; return; } - VectorTy &Vec = *getAsVector(); - VectorTy::iterator I = std::find(Vec.begin(), Vec.end(), - reinterpret_cast<uintptr_t>(D)); + DeclsTy &Vec = *getAsVector(); + DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); assert(I != Vec.end() && "list does not contain decl"); Vec.erase(I); - assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D)) + assert(std::find(Vec.begin(), Vec.end(), D) == Vec.end() && "list still contains decl"); } /// getLookupResult - Return an array of all the decls that this list /// represents. - DeclContext::lookup_result getLookupResult(ASTContext &Context) { + DeclContext::lookup_result getLookupResult() { if (isNull()) return DeclContext::lookup_result(DeclContext::lookup_iterator(0), DeclContext::lookup_iterator(0)); - if (hasDeclarationIDs()) - materializeDecls(Context); - // If we have a single NamedDecl, return it. if (getAsDecl()) { assert(!isNull() && "Empty list isn't allowed"); @@ -172,19 +114,15 @@ public: } assert(getAsVector() && "Must have a vector at this point"); - VectorTy &Vector = *getAsVector(); + DeclsTy &Vector = *getAsVector(); // Otherwise, we have a range result. - return DeclContext::lookup_result((NamedDecl **)&Vector[0], - (NamedDecl **)&Vector[0]+Vector.size()); + return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size()); } /// HandleRedeclaration - If this is a redeclaration of an existing decl, /// replace the old one with D and return true. Otherwise return false. - bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { - if (hasDeclarationIDs()) - materializeDecls(Context); - + bool HandleRedeclaration(NamedDecl *D) { // Most decls only have one entry in their list, special case it. if (NamedDecl *OldD = getAsDecl()) { if (!D->declarationReplaces(OldD)) @@ -194,12 +132,12 @@ public: } // Determine if this declaration is actually a redeclaration. - VectorTy &Vec = *getAsVector(); - for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); + DeclsTy &Vec = *getAsVector(); + for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); OD != ODEnd; ++OD) { - NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); + NamedDecl *OldD = *OD; if (D->declarationReplaces(OldD)) { - *OD = reinterpret_cast<uintptr_t>(D); + *OD = D; return true; } } @@ -211,17 +149,15 @@ public: /// not a redeclaration to merge it into the appropriate place in our list. /// void AddSubsequentDecl(NamedDecl *D) { - assert(!hasDeclarationIDs() && "Must materialize before adding decls"); - // If this is the second decl added to the list, convert this to vector // form. if (NamedDecl *OldD = getAsDecl()) { - VectorTy *VT = new VectorTy(); - VT->push_back(reinterpret_cast<uintptr_t>(OldD)); - Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; + DeclsTy *VT = new DeclsTy(); + VT->push_back(OldD); + Data = VT; } - VectorTy &Vec = *getAsVector(); + DeclsTy &Vec = *getAsVector(); // Using directives end up in a special entry which contains only // other using directives, so all this logic is wasted for them. @@ -232,32 +168,30 @@ public: // iterator which points at the first tag will start a span of // decls that only contains tags. if (D->hasTagIdentifierNamespace()) - Vec.push_back(reinterpret_cast<uintptr_t>(D)); + Vec.push_back(D); // Resolved using declarations go at the front of the list so that // they won't show up in other lookup results. Unresolved using // declarations (which are always in IDNS_Using | IDNS_Ordinary) // follow that so that the using declarations will be contiguous. else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { - VectorTy::iterator I = Vec.begin(); + DeclsTy::iterator I = Vec.begin(); if (D->getIdentifierNamespace() != Decl::IDNS_Using) { while (I != Vec.end() && - reinterpret_cast<NamedDecl *>(*I) - ->getIdentifierNamespace() == Decl::IDNS_Using) + (*I)->getIdentifierNamespace() == Decl::IDNS_Using) ++I; } - Vec.insert(I, reinterpret_cast<uintptr_t>(D)); + Vec.insert(I, D); // All other declarations go at the end of the list, but before any // tag declarations. But we can be clever about tag declarations // because there can only ever be one in a scope. - } else if (reinterpret_cast<NamedDecl *>(Vec.back()) - ->hasTagIdentifierNamespace()) { - uintptr_t TagD = Vec.back(); - Vec.back() = reinterpret_cast<uintptr_t>(D); + } else if (Vec.back()->hasTagIdentifierNamespace()) { + NamedDecl *TagD = Vec.back(); + Vec.back() = D; Vec.push_back(TagD); } else - Vec.push_back(reinterpret_cast<uintptr_t>(D)); + Vec.push_back(D); } }; diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 2807d16..4b5e6fd 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -68,16 +68,16 @@ public: SourceLocation FriendL); static FriendDecl *Create(ASTContext &C, EmptyShell Empty); - /// If this friend declaration names an (untemplated but - /// possibly dependent) type, return the type; otherwise - /// return null. This is used only for C++0x's unelaborated - /// friend type declarations. + /// 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*>(); } - /// If this friend declaration doesn't name an unelaborated - /// type, return the inner declaration. + /// If this friend declaration doesn't name a type, return the inner + /// declaration. NamedDecl *getFriendDecl() const { return Friend.dyn_cast<NamedDecl*>(); } @@ -92,8 +92,8 @@ public: static bool classof(const FriendDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::Friend; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// An iterator over the friend declarations of a class. diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index e1fae8f..030291e 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -34,7 +34,6 @@ private: public: static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); - void Destroy(ASTContext& C); unsigned size() const { return NumDecls; } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 30f63d8..ad26748 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -21,7 +21,6 @@ namespace clang { class Expr; class Stmt; class FunctionDecl; -class AttributeList; class RecordDecl; class ObjCIvarDecl; class ObjCMethodDecl; @@ -41,12 +40,6 @@ protected: public: ObjCListBase() : List(0), NumElts(0) {} - ~ObjCListBase() { - assert(List == 0 && "Destroy should have been called before dtor"); - } - - void Destroy(ASTContext &Ctx); - unsigned size() const { return NumElts; } bool empty() const { return NumElts == 0; } @@ -92,7 +85,6 @@ public: void set(ObjCProtocolDecl* const* InList, unsigned Elts, const SourceLocation *Locs, ASTContext &Ctx); - void Destroy(ASTContext &Ctx); }; @@ -128,6 +120,9 @@ private: // Synthesized declaration method for a property setter/getter bool IsSynthesized : 1; + + // Method has a definition. + bool IsDefined : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional @@ -171,29 +166,25 @@ private: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, + bool isDefined = false, ImplementationControl impControl = None, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), + IsDefined(isDefined), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), NumSelectorArgs(numSelectorArgs), MethodDeclType(T), ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} - virtual ~ObjCMethodDecl() {} - /// \brief A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. virtual ObjCMethodDecl *getNextRedeclaration(); public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCMethodDecl *Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, @@ -203,6 +194,7 @@ public: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, + bool isDefined = false, ImplementationControl impControl = None, unsigned numSelectorArgs = 0); @@ -296,6 +288,9 @@ public: bool isSynthesized() const { return IsSynthesized; } void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } + + bool isDefined() const { return IsDefined; } + void setDefined(bool isDefined) { IsDefined = isDefined; } // Related to protocols declared in @protocol void setDeclImplementation(ImplementationControl ic) { @@ -326,21 +321,6 @@ public: } }; -/// ObjCMethodList - a linked list of methods with different signatures. -struct ObjCMethodList { - ObjCMethodDecl *Method; - ObjCMethodList *Next; - - ObjCMethodList() { - Method = 0; - Next = 0; - } - ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { - Method = M; - Next = C; - } -}; - /// ObjCContainerDecl - Represents a container for method declarations. /// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, /// ObjCProtocolDecl, and ObjCImplDecl. @@ -355,8 +335,6 @@ public: IdentifierInfo *Id) : NamedDecl(DK, DC, L, Id), DeclContext(DK) {} - virtual ~ObjCContainerDecl() {} - // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; prop_iterator prop_begin() const { @@ -465,12 +443,19 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// Class's super class. ObjCInterfaceDecl *SuperClass; - /// Protocols referenced in interface header declaration + /// Protocols referenced in the @interface declaration ObjCProtocolList ReferencedProtocols; + + /// Protocols reference in both the @interface and class extensions. + ObjCList<ObjCProtocolDecl> AllReferencedProtocols; /// List of categories defined for this class. /// FIXME: Why is this a linked list?? ObjCCategoryDecl *CategoryList; + + /// IvarList - List of all ivars defined by this class; including class + /// extensions and implementation. This list is built lazily. + ObjCIvarDecl *IvarList; bool ForwardDecl:1; // declared with @class. bool InternalInterface:1; // true - no @interface for @implementation @@ -482,13 +467,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal); - virtual ~ObjCInterfaceDecl() {} - public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, @@ -513,25 +492,49 @@ public: } typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } + + protocol_iterator protocol_begin() const { + return ReferencedProtocols.begin(); + } + protocol_iterator protocol_end() const { + return ReferencedProtocols.end(); + } + typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; + protocol_loc_iterator protocol_loc_begin() const { return ReferencedProtocols.loc_begin(); } + protocol_loc_iterator protocol_loc_end() const { return ReferencedProtocols.loc_end(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } + + typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; + + all_protocol_iterator all_referenced_protocol_begin() const { + return AllReferencedProtocols.empty() ? protocol_begin() + : AllReferencedProtocols.begin(); + } + all_protocol_iterator all_referenced_protocol_end() const { + return AllReferencedProtocols.empty() ? protocol_end() + : AllReferencedProtocols.end(); + } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } - + + ObjCIvarDecl *all_declared_ivar_begin(); + void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; } + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, @@ -543,7 +546,6 @@ public: /// into the protocol list for this class. void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num, - const SourceLocation *Locs, ASTContext &C); bool isForwardDecl() const { return ForwardDecl; } @@ -625,6 +627,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCInterfaceDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCInterface; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC @@ -650,21 +655,26 @@ public: private: ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) + QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, + bool synthesized) : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - DeclAccess(ac) {} + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - AccessControl ac, Expr *BW = NULL); + AccessControl ac, Expr *BW = NULL, + bool synthesized=false); /// \brief Return the class interface that this ivar is logically contained /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. const ObjCInterfaceDecl *getContainingInterface() const; + + ObjCIvarDecl *getNextIvar() { return NextIvar; } + void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } void setAccessControl(AccessControl ac) { DeclAccess = ac; } @@ -674,13 +684,21 @@ public: return DeclAccess == None ? Protected : AccessControl(DeclAccess); } + void setSynthesize(bool synth) { Synthesized = synth; } + bool getSynthesize() const { return Synthesized; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCIvarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCIvar; } private: + /// NextIvar - Next Ivar in the list of ivars declared in class; class's + /// extensions and class's implementation + ObjCIvarDecl *NextIvar; + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; + unsigned Synthesized : 1; }; @@ -700,8 +718,6 @@ public: IdentifierInfo *Id, QualType T, Expr *BW); - virtual void Destroy(ASTContext& C); - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } @@ -745,15 +761,10 @@ class ObjCProtocolDecl : public ObjCContainerDecl { isForwardProtoDecl(true) { } - virtual ~ObjCProtocolDecl() {} - public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - const ObjCProtocolList &getReferencedProtocols() const { return ReferencedProtocols; } @@ -822,12 +833,7 @@ private: ObjCClassDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, unsigned nElts, ASTContext &C); - virtual ~ObjCClassDecl() {} public: - - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts = 0, const SourceLocation *Locs = 0, @@ -860,7 +866,6 @@ class ObjCForwardProtocolDecl : public Decl { ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, ObjCProtocolDecl *const *Elts, unsigned nElts, const SourceLocation *Locs, ASTContext &C); - virtual ~ObjCForwardProtocolDecl() {} public: static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, @@ -874,9 +879,6 @@ public: return Create(C, DC, L, 0, 0, 0); } - /// Destroy - Call destructors and release memory. - virtual void Destroy(ASTContext& C); - typedef ObjCProtocolList::iterator protocol_iterator; protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } @@ -928,6 +930,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + /// \brief The location of the '@' in '@interface' SourceLocation AtLoc; @@ -938,8 +943,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id) : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id), - ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc), - CategoryNameLoc(CategoryNameLoc) { + ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false), + AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) { } public: @@ -991,6 +996,9 @@ public: bool IsClassExtension() const { return getIdentifier() == 0; } const ObjCCategoryDecl *getNextClassExtension() const; + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1032,8 +1040,6 @@ protected: ClassInterface(classInterface) {} public: - virtual ~ObjCImplDecl() {} - const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } void setClassInterface(ObjCInterfaceDecl *IFace); @@ -1165,11 +1171,15 @@ class ObjCImplementationDecl : public ObjCImplDecl { CXXBaseOrMemberInitializer **IvarInitializers; unsigned NumIvarInitializers; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), - SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), + HasSynthBitfield(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1207,6 +1217,9 @@ public: void setIvarInitializers(ASTContext &C, CXXBaseOrMemberInitializer ** initializers, unsigned numInitializers); + + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. @@ -1262,6 +1275,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplementationDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCImplementation; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 135dd3a..b532668 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -23,6 +23,7 @@ namespace clang { class TemplateParameterList; class TemplateDecl; +class RedeclarableTemplateDecl; class FunctionTemplateDecl; class ClassTemplateDecl; class ClassTemplatePartialSpecializationDecl; @@ -193,13 +194,6 @@ public: TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { } - /// Used to release the memory associated with a TemplateArgumentList - /// object. FIXME: This is currently not called anywhere, but the - /// memory will still be freed when using a BumpPtrAllocator. - void Destroy(ASTContext &C); - - ~TemplateArgumentList(); - /// \brief Copies the template arguments into a locally new[]'d array. void init(ASTContext &Context, const TemplateArgument *Args, unsigned NumArgs); @@ -255,8 +249,6 @@ protected: : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) { } public: - ~TemplateDecl(); - /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -268,6 +260,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } @@ -490,122 +483,179 @@ public: } }; -/// Declaration of a template function. -class FunctionTemplateDecl : public TemplateDecl { - static void DeallocateCommon(void *Ptr); - +/// Declaration of a redeclarable template. +class RedeclarableTemplateDecl : public TemplateDecl { + + RedeclarableTemplateDecl *getPreviousDeclarationImpl() { + return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>(); + } + + RedeclarableTemplateDecl *getCanonicalDeclImpl(); + + void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev); + + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(TD); + } + protected: - /// \brief Data that is common to all of the declarations of a given - /// function template. - struct Common { - Common() : InstantiatedFromMember(0, false) { } + template <typename EntryType> struct SpecEntryTraits { + typedef EntryType DeclType; - /// \brief The function template specializations for this function - /// template, including explicit specializations and instantiations. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + static DeclType *getMostRecentDeclaration(EntryType *D) { + return D->getMostRecentDeclaration(); + } + }; + + template <typename EntryType, + typename _SETraits = SpecEntryTraits<EntryType>, + typename _DeclType = typename _SETraits::DeclType> + class SpecIterator : public std::iterator<std::forward_iterator_tag, + _DeclType*, ptrdiff_t, + _DeclType*, _DeclType*> { + typedef _SETraits SETraits; + typedef _DeclType DeclType; + + typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType; + + SetIteratorType SetIter; + + public: + SpecIterator() : SetIter() {} + SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {} + + DeclType *operator*() const { + return SETraits::getMostRecentDeclaration(&*SetIter); + } + DeclType *operator->() const { return **this; } + + SpecIterator &operator++() { ++SetIter; return *this; } + SpecIterator operator++(int) { + SpecIterator tmp(*this); + ++(*this); + return tmp; + } + + bool operator==(SpecIterator Other) const { + return SetIter == Other.SetIter; + } + bool operator!=(SpecIterator Other) const { + return SetIter != Other.SetIter; + } + }; + + template <typename EntryType> + SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs, + bool isEnd) { + return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); + } + + template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* + findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs, + const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + struct CommonBase { + CommonBase() : InstantiatedFromMember(0, false) { } - /// \brief The member function template from which this was most + /// \brief The template from which this was most /// directly instantiated (or null). /// - /// The boolean value indicates whether this member function template + /// The boolean value indicates whether this template /// was explicitly specialized. - llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember; + llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> + InstantiatedFromMember; + + /// \brief The latest declaration of this template. + RedeclarableTemplateDecl *Latest; }; /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this function - /// template. - llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev; + /// or to the data that is common to all declarations of this template. + llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev; - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same function template. Calling this routine - /// may implicitly allocate memory for the common pointer. - Common *getCommonPtr(); + /// \brief Retrieves the "common" pointer shared by all (re-)declarations of + /// the same template. Calling this routine may implicitly allocate memory + /// for the common pointer. + CommonBase *getCommonPtr(); - FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + virtual CommonBase *newCommon() = 0; -public: - void Destroy(ASTContext &C); + // Construct a template decl with name, parameters, and templated element. + RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : TemplateDecl(DK, DC, L, Name, Params, Decl), + CommonOrPrev((CommonBase*)0) { } - /// Get the underlying function declaration of the template. - FunctionDecl *getTemplatedDecl() const { - return static_cast<FunctionDecl*>(TemplatedDecl); - } +public: + template <class decl_type> friend class RedeclarableTemplate; - /// \brief Retrieve the set of function template specializations of this - /// function template. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { - return getCommonPtr()->Specializations; + RedeclarableTemplateDecl *getCanonicalDecl() { + return getCanonicalDeclImpl(); } - /// \brief Retrieve the previous declaration of this function template, or + /// \brief Retrieve the previous declaration of this template, or /// NULL if no such declaration exists. - const FunctionTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + RedeclarableTemplateDecl *getPreviousDeclaration() { + return getPreviousDeclarationImpl(); } - /// \brief Retrieve the previous declaration of this function template, or + /// \brief Retrieve the previous declaration of this template, or /// NULL if no such declaration exists. - FunctionTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + const RedeclarableTemplateDecl *getPreviousDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration(); } - /// \brief Set the previous declaration of this function template. - void setPreviousDeclaration(FunctionTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; + /// \brief Retrieve the first declaration of this template, or itself + /// if this the first one. + RedeclarableTemplateDecl *getFirstDeclaration() { + return getCanonicalDecl(); } - virtual FunctionTemplateDecl *getCanonicalDecl(); + /// \brief Retrieve the first declaration of this template, or itself + /// if this the first one. + const RedeclarableTemplateDecl *getFirstDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration(); + } - /// \brief Retrieve the member function template that this function template - /// was instantiated from. - /// - /// This routine will return non-NULL for member function templates of - /// class templates. For example, given: - /// - /// \code - /// template <typename T> - /// struct X { - /// template <typename U> void f(); - /// }; - /// \endcode - /// - /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a - /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will - /// return X<int>::f, a FunctionTemplateDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a - /// ClassTemplateDecl). - /// - /// \returns NULL if this is not an instantiation of a member function - /// template. - FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + /// \brief Retrieve the most recent declaration of this template, or itself + /// if this the most recent one. + RedeclarableTemplateDecl *getMostRecentDeclaration() { + return getCommonPtr()->Latest; } - void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(FTD); + /// \brief Retrieve the most recent declaration of this template, or itself + /// if this the most recent one. + const RedeclarableTemplateDecl *getMostRecentDeclaration() const { + return + const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration(); } /// \brief Determines whether this template was a specialization of a /// member template. /// - /// In the following example, the function template \c X<int>::f is a - /// member specialization. + /// In the following example, the function template \c X<int>::f and the + /// member template \c X<int>::Inner are member specializations. /// /// \code /// template<typename T> /// struct X { /// template<typename U> void f(T, U); + /// template<typename U> struct Inner; /// }; /// /// template<> template<typename T> /// void X<int>::f(int, T); + /// template<> template<typename T> + /// struct X<int>::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() { return getCommonPtr()->InstantiatedFromMember.getInt(); @@ -618,6 +668,197 @@ public: getCommonPtr()->InstantiatedFromMember.setInt(true); } + /// \brief Retrieve the previous declaration of this template, or + /// NULL if no such declaration exists. + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { + return getInstantiatedFromMemberTemplateImpl(); + } + + virtual RedeclarableTemplateDecl *getNextRedeclaration(); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + +template <class decl_type> +class RedeclarableTemplate { + RedeclarableTemplateDecl *thisDecl() { + return static_cast<decl_type*>(this); + } + +public: + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + decl_type *getPreviousDeclaration() { + return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl()); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const decl_type *getPreviousDeclaration() const { + return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration(); + } + + /// \brief Set the previous declaration of this function template. + void setPreviousDeclaration(decl_type *Prev) { + thisDecl()->setPreviousDeclarationImpl(Prev); + } + + decl_type *getCanonicalDecl() { + return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl()); + } + + const decl_type *getCanonicalDecl() const { + return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl(); + } + + /// \brief Retrieve the member template that this template was instantiated + /// from. + /// + /// This routine will return non-NULL for member templates of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> void f(); + /// template <typename U> struct A {}; + /// }; + /// \endcode + /// + /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a + /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will + /// return X<int>::f, a FunctionTemplateDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a + /// ClassTemplateDecl). + /// + /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent + /// is X<int>, also a CTSD) for which getSpecializedTemplate() will + /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD). + /// + /// \returns NULL if this is not an instantiation of a member template. + decl_type *getInstantiatedFromMemberTemplate() { + return static_cast<decl_type*>( + thisDecl()->getInstantiatedFromMemberTemplateImpl()); + } + + void setInstantiatedFromMemberTemplate(decl_type *TD) { + thisDecl()->setInstantiatedFromMemberTemplateImpl(TD); + } +}; + +template <> struct RedeclarableTemplateDecl:: +SpecEntryTraits<FunctionTemplateSpecializationInfo> { + typedef FunctionDecl DeclType; + + static DeclType * + getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) { + return I->Function->getMostRecentDeclaration(); + } +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate<FunctionTemplateDecl> { + static void DeallocateCommon(void *Ptr); + +protected: + typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base; + + /// \brief Data that is common to all of the declarations of a given + /// function template. + struct Common : CommonBase { + /// \brief The function template specializations for this function + /// template, including explicit specializations and instantiations. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + }; + + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); + } + + friend void FunctionDecl::setFunctionTemplateSpecialization( + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { + return getCommonPtr()->Specializations; + } + +public: + /// Get the underlying function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast<FunctionDecl*>(TemplatedDecl); + } + + /// Returns whether this template declaration defines the primary + /// pattern. + bool isThisDeclarationADefinition() const { + return getTemplatedDecl()->isThisDeclarationADefinition(); + } + + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + FunctionDecl *findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos); + + FunctionTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const FunctionTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + FunctionTemplateDecl *getPreviousDeclaration() { + return redeclarable_base::getPreviousDeclaration(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const FunctionTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); + } + + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); + } + + typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; + + spec_iterator spec_begin() { + return makeSpecIterator(getSpecializations(), false); + } + + spec_iterator spec_end() { + return makeSpecIterator(getSpecializations(), true); + } + /// Create a template function node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -630,8 +871,8 @@ public: static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == FunctionTemplate; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; //===----------------------------------------------------------------------===// @@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, - VarDecl::None), + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false) { } @@ -904,13 +1144,20 @@ public: DefaultArgumentWasInherited = false; } + SourceRange getSourceRange() const { + SourceLocation End = getLocation(); + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + End = getDefaultArgument().getSourceRange().getEnd(); + return SourceRange(getTemplateParameters()->getTemplateLoc(), End); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// \brief Represents a class template specialization, which refers to @@ -991,12 +1238,21 @@ public: static ClassTemplateSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); - virtual void Destroy(ASTContext& C); - virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; + ClassTemplateSpecializationDecl *getMostRecentDeclaration() { + CXXRecordDecl *Recent + = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration()); + if (!isa<ClassTemplateSpecializationDecl>(Recent)) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration()); + Recent = Recent->getPreviousDeclaration(); + } + return cast<ClassTemplateSpecializationDecl>(Recent); + } + /// \brief Retrieve the template that this specialization specializes. ClassTemplateDecl *getSpecializedTemplate() const; @@ -1044,7 +1300,8 @@ public: if (getSpecializationKind() != TSK_ImplicitInstantiation && getSpecializationKind() != TSK_ExplicitInstantiationDefinition && getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) - return (ClassTemplateDecl*)0; + return llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *>(); if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) @@ -1123,7 +1380,8 @@ public: /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = T; } /// \brief Gets the type of this specialization as it was written by @@ -1138,13 +1396,15 @@ public: } /// \brief Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->ExternLoc = Loc; } /// \brief Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } /// \brief Gets the location of the template keyword, if present. @@ -1242,6 +1502,11 @@ public: static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); + ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() { + return cast<ClassTemplatePartialSpecializationDecl>( + ClassTemplateSpecializationDecl::getMostRecentDeclaration()); + } + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -1355,15 +1620,16 @@ public: }; /// Declaration of a class template. -class ClassTemplateDecl : public TemplateDecl { +class ClassTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate<ClassTemplateDecl> { static void DeallocateCommon(void *Ptr); protected: + typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base; + /// \brief Data that is common to all of the declarations of a given /// class template. - struct Common { - Common() : InstantiatedFromMember(0, 0) {} - + struct Common : CommonBase { /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; @@ -1375,28 +1641,29 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; - - /// \brief The templated member class from which this was most - /// directly instantiated (or null). - /// - /// The boolean value indicates whether this member class template - /// was explicitly specialized. - llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember; }; - /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this class template. - llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev; + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { + return getCommonPtr()->Specializations; + } - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same class template. Calling this routine - /// may implicitly allocate memory for the common pointer. - Common *getCommonPtr(); + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & + getPartialSpecializations() { + return getCommonPtr()->PartialSpecializations; + } ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); + } public: /// Get the underlying class declarations of the template. @@ -1404,48 +1671,71 @@ public: return static_cast<CXXRecordDecl *>(TemplatedDecl); } - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. - const ClassTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + /// Returns whether this template declaration defines the primary + /// class pattern. + bool isThisDeclarationADefinition() const { + return getTemplatedDecl()->isThisDeclarationADefinition(); } - /// \brief Retrieve the previous declaration of this function template, or + /// Create a class template node. + static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl, + ClassTemplateDecl *PrevDecl); + + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + ClassTemplateSpecializationDecl * + findSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified specialization knowing that it is not already + /// in. InsertPos must be obtained from findSpecialization. + void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { + getSpecializations().InsertNode(D, InsertPos); + } + + ClassTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const ClassTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this class template, or /// NULL if no such declaration exists. ClassTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + return redeclarable_base::getPreviousDeclaration(); } - /// \brief Set the previous declaration of this class template. - void setPreviousDeclaration(ClassTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; + /// \brief Retrieve the previous declaration of this class template, or + /// NULL if no such declaration exists. + const ClassTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); } - virtual ClassTemplateDecl *getCanonicalDecl(); - - const ClassTemplateDecl *getCanonicalDecl() const { - return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl(); + ClassTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); } - /// Create a class template node. - static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName Name, - TemplateParameterList *Params, - NamedDecl *Decl, - ClassTemplateDecl *PrevDecl); + /// \brief Return the partial specialization with the provided arguments if it + /// exists, otherwise return the insertion point. + ClassTemplatePartialSpecializationDecl * + findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); - /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { - return getCommonPtr()->Specializations; + /// \brief Insert the specified partial specialization knowing that it is not + /// already in. InsertPos must be obtained from findPartialSpecialization. + void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, + void *InsertPos) { + getPartialSpecializations().InsertNode(D, InsertPos); } - /// \brief Retrieve the set of partial specializations of this class - /// template. - llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & - getPartialSpecializations() { - return getCommonPtr()->PartialSpecializations; + /// \brief Return the next partial specialization sequence number. + unsigned getNextPartialSpecSequenceNumber() { + return getPartialSpecializations().size(); } /// \brief Retrieve the partial specializations as an ordered list. @@ -1455,12 +1745,24 @@ public: /// \brief Find a class template partial specialization with the given /// type T. /// - /// \brief A dependent type that names a specialization of this class + /// \param T a dependent type that names a specialization of this class /// template. /// /// \returns the class template partial specialization that exactly matches /// the type \p T, or NULL if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); + + /// \brief Find a class template partial specialization which was instantiated + /// from the given member partial specialization. + /// + /// \param D a member class template partial specialization. + /// + /// \returns the class template partial specialization which was instantiated + /// from the given member partial specialization, or NULL if no such partial + /// specialization exists. + ClassTemplatePartialSpecializationDecl * + findPartialSpecInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *D); /// \brief Retrieve the template specialization type of the /// injected-class-name for this class template. @@ -1478,78 +1780,45 @@ public: /// \endcode QualType getInjectedClassNameSpecialization(); - /// \brief Retrieve the member class template that this class template was - /// derived from. - /// - /// This routine will return non-NULL for templated member classes of - /// class templates. For example, given: - /// - /// \code - /// template <typename T> - /// struct X { - /// template <typename U> struct A {}; - /// }; - /// \endcode - /// - /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent - /// is X<int>, also a CTSD) for which getSpecializedTemplate() will - /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD). - /// - /// \returns null if this is not an instantiation of a member class template. - ClassTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator; + + spec_iterator spec_begin() { + return makeSpecIterator(getSpecializations(), false); } - void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(CTD); + spec_iterator spec_end() { + return makeSpecIterator(getSpecializations(), true); } - /// \brief Determines whether this template was a specialization of a - /// member template. - /// - /// In the following example, the member template \c X<int>::Inner is a - /// member specialization. - /// - /// \code - /// template<typename T> - /// struct X { - /// template<typename U> struct Inner; - /// }; - /// - /// template<> template<typename T> - /// struct X<int>::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() { - return getCommonPtr()->InstantiatedFromMember.getInt(); + typedef SpecIterator<ClassTemplatePartialSpecializationDecl> + partial_spec_iterator; + + partial_spec_iterator partial_spec_begin() { + return makeSpecIterator(getPartialSpecializations(), false); } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); + + partial_spec_iterator partial_spec_end() { + return makeSpecIterator(getPartialSpecializations(), true); } - + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == ClassTemplate; } - virtual void Destroy(ASTContext& C); - - friend class PCHDeclReader; - friend class PCHDeclWriter; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// Declaration of a friend template. For example: /// /// template <typename T> class A { /// friend class MyVector<T>; // not a friend template -/// template <typename U> friend class B; // friend template +/// template <typename U> friend class B; // not a friend template /// template <typename U> friend class Foo<T>::Nested; // friend template +/// }; +/// NOTE: This class is not currently in use. All of the above +/// will yield a FriendDecl, not a FriendTemplateDecl. class FriendTemplateDecl : public Decl { public: typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; @@ -1580,6 +1849,12 @@ private: FriendLoc(FriendLoc) {} + FriendTemplateDecl(EmptyShell Empty) + : Decl(Decl::FriendTemplate, Empty), + NumParams(0), + Params(0) + {} + public: static FriendTemplateDecl *Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc, @@ -1588,6 +1863,8 @@ public: FriendUnion Friend, SourceLocation FriendLoc); + static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty); + /// If this friend declaration names a templated type (or /// a dependent member type of a templated type), return that /// type; otherwise return null. @@ -1620,6 +1897,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } static bool classof(const FriendTemplateDecl *D) { return true; } + + friend class ASTDeclReader; }; /// Implementation of inline functions that require the template declarations diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 8a771d5..8bb6275 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -30,6 +30,7 @@ namespace clang { class IdentifierInfo; class MultiKeywordSelector; class UsingDirectiveDecl; + class TypeSourceInfo; /// DeclarationName - The name of a declaration. In the common case, /// this just stores an IdentifierInfo pointer to a normal @@ -367,6 +368,146 @@ public: DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); }; +/// DeclarationNameLoc - Additional source/type location info +/// for a declaration name. Needs a DeclarationName in order +/// to be interpreted correctly. +struct DeclarationNameLoc { + union { + // The source location for identifier stored elsewhere. + // struct {} Identifier; + + // Type info for constructors, destructors and conversion functions. + // Locations (if any) for the tilde (destructor) or operator keyword + // (conversion) are stored elsewhere. + struct { + TypeSourceInfo* TInfo; + } NamedType; + + // The location (if any) of the operator keyword is stored elsewhere. + struct { + unsigned BeginOpNameLoc; + unsigned EndOpNameLoc; + } CXXOperatorName; + + // The location (if any) of the operator keyword is stored elsewhere. + struct { + unsigned OpNameLoc; + } CXXLiteralOperatorName; + + // struct {} CXXUsingDirective; + // struct {} ObjCZeroArgSelector; + // struct {} ObjCOneArgSelector; + // struct {} ObjCMultiArgSelector; + }; + + DeclarationNameLoc(DeclarationName Name); + // FIXME: this should go away once all DNLocs are properly initialized. + DeclarationNameLoc() { NamedType.TInfo = 0; } +}; // struct DeclarationNameLoc + + +/// DeclarationNameInfo - A collector data type for bundling together +/// a DeclarationName and the correspnding source/type location info. +struct DeclarationNameInfo { +private: + /// Name - The declaration name, also encoding name kind. + DeclarationName Name; + /// Loc - The main source location for the declaration name. + SourceLocation NameLoc; + /// Info - Further source/type location info for special kinds of names. + DeclarationNameLoc LocInfo; + +public: + // FIXME: remove it. + DeclarationNameInfo() {} + + DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc) + : Name(Name), NameLoc(NameLoc), LocInfo(Name) {} + + DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc, + DeclarationNameLoc LocInfo) + : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {} + + /// getName - Returns the embedded declaration name. + DeclarationName getName() const { return Name; } + /// setName - Sets the embedded declaration name. + void setName(DeclarationName N) { Name = N; } + + /// getLoc - Returns the main location of the declaration name. + SourceLocation getLoc() const { return NameLoc; } + /// setLoc - Sets the main location of the declaration name. + void setLoc(SourceLocation L) { NameLoc = L; } + + const DeclarationNameLoc &getInfo() const { return LocInfo; } + DeclarationNameLoc &getInfo() { return LocInfo; } + void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; } + + /// getNamedTypeInfo - Returns the source type info associated to + /// the name. Assumes it is a constructor, destructor or conversion. + TypeSourceInfo *getNamedTypeInfo() const { + assert(Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName); + return LocInfo.NamedType.TInfo; + } + /// setNamedTypeInfo - Sets the source type info associated to + /// the name. Assumes it is a constructor, destructor or conversion. + void setNamedTypeInfo(TypeSourceInfo *TInfo) { + assert(Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName); + LocInfo.NamedType.TInfo = TInfo; + } + + /// getCXXOperatorNameRange - Gets the range of the operator name + /// (without the operator keyword). Assumes it is a (non-literal) operator. + SourceRange getCXXOperatorNameRange() const { + assert(Name.getNameKind() == DeclarationName::CXXOperatorName); + return SourceRange( + SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc), + SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc) + ); + } + /// setCXXOperatorNameRange - Sets the range of the operator name + /// (without the operator keyword). Assumes it is a C++ operator. + void setCXXOperatorNameRange(SourceRange R) { + assert(Name.getNameKind() == DeclarationName::CXXOperatorName); + LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding(); + LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding(); + } + + /// getCXXLiteralOperatorNameLoc - Returns the location of the literal + /// operator name (not the operator keyword). + /// Assumes it is a literal operator. + SourceLocation getCXXLiteralOperatorNameLoc() const { + assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); + return SourceLocation:: + getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc); + } + /// setCXXLiteralOperatorNameLoc - Sets the location of the literal + /// operator name (not the operator keyword). + /// Assumes it is a literal operator. + void setCXXLiteralOperatorNameLoc(SourceLocation Loc) { + assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); + LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); + } + + /// getAsString - Retrieve the human-readable string for this name. + std::string getAsString() const; + + /// printName - Print the human-readable name to a stream. + void printName(llvm::raw_ostream &OS) const; + + /// getBeginLoc - Retrieve the location of the first token. + SourceLocation getBeginLoc() const { return NameLoc; } + /// getEndLoc - Retrieve the location of the last token. + SourceLocation getEndLoc() const; + /// getSourceRange - The range of the declaration name. + SourceRange getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); + } +}; + /// Insertion operator for diagnostics. This allows sending DeclarationName's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, return PD; } +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + DeclarationNameInfo DNInfo) { + DNInfo.printName(OS); + return OS; +} + } // end namespace clang namespace llvm { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ade2b09..48130be 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -18,6 +18,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/AST/DeclAccessPair.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/APSInt.h" @@ -42,7 +43,7 @@ namespace clang { class TemplateArgumentListInfo; /// \brief A simple array of base specifiers. -typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; +typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -61,8 +62,14 @@ protected: /// (C++ [temp.dep.constexpr]). bool ValueDependent : 1; + /// ValueKind - The value classification of this expression. + /// Only actually used by certain subclasses. + unsigned ValueKind : 2; + + enum { BitsRemaining = 28 }; + Expr(StmtClass SC, QualType T, bool TD, bool VD) - : Stmt(SC), TypeDependent(TD), ValueDependent(VD) { + : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) { setType(T); } @@ -258,7 +265,6 @@ public: /// function returning an rvalue reference. /// lvalues and xvalues are collectively referred to as glvalues, while /// prvalues and xvalues together form rvalues. - /// If a Classification Classify(ASTContext &Ctx) const { return ClassifyImpl(Ctx, 0); } @@ -310,7 +316,7 @@ public: } /// isConstantInitializer - Returns true if this expression is a constant /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx) const; + bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { @@ -521,10 +527,14 @@ class DeclRefExpr : public Expr { // (2) the declaration's name was followed by an explicit template // argument list. llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; - + // Loc - The location of the declaration name itself. SourceLocation Loc; + /// DNLoc - Provides source/type location info for the + /// declaration name embedded in DecoratedD. + DeclarationNameLoc DNLoc; + /// \brief Retrieve the qualifier that preceded the declaration name, if any. NameQualifier *getNameQualifier() { if ((DecoratedD.getInt() & HasQualifierFlag) == 0) @@ -537,31 +547,17 @@ class DeclRefExpr : public Expr { const NameQualifier *getNameQualifier() const { return const_cast<DeclRefExpr *>(this)->getNameQualifier(); } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0) - return 0; - - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return reinterpret_cast<ExplicitTemplateArgumentList *>( - getNameQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList(); - } - + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, QualType T); + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + ValueDecl *D, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + QualType T); + /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } @@ -584,6 +580,14 @@ public: QualType T, const TemplateArgumentListInfo *TemplateArgs = 0); + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + ValueDecl *D, + const DeclarationNameInfo &NameInfo, + QualType T, + const TemplateArgumentListInfo *TemplateArgs = 0); + /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, bool HasQualifier, unsigned NumTemplateArgs); @@ -592,6 +596,10 @@ public: const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); + } + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const; @@ -619,53 +627,77 @@ public: return getNameQualifier()->NNS; } - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() const { - return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; + bool hasExplicitTemplateArgs() const { + return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs(); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgumentList()) - getExplicitTemplateArgumentList()->copyInto(List); + if (hasExplicitTemplateArgs()) + getExplicitTemplateArgs().copyInto(List); } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return SourceLocation(); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { - if (!hasExplicitTemplateArgumentList()) + if (!hasExplicitTemplateArgs()) return SourceLocation(); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; } static bool classof(const Stmt *T) { @@ -677,8 +709,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. @@ -725,28 +757,84 @@ public: virtual child_iterator child_end(); }; +/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without +/// leaking memory. +/// +/// For large floats/integers, APFloat/APInt will allocate memory from the heap +/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator +/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with +/// the APFloat/APInt values will never get freed. APNumericStorage uses +/// ASTContext's allocator for memory allocation. +class APNumericStorage { + unsigned BitWidth; + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } + + APNumericStorage(const APNumericStorage&); // do not implement + APNumericStorage& operator=(const APNumericStorage&); // do not implement + +protected: + APNumericStorage() : BitWidth(0), VAL(0) { } + + llvm::APInt getIntValue() const { + unsigned NumWords = llvm::APInt::getNumWords(BitWidth); + if (NumWords > 1) + return llvm::APInt(BitWidth, NumWords, pVal); + else + return llvm::APInt(BitWidth, VAL); + } + void setIntValue(ASTContext &C, const llvm::APInt &Val); +}; + +class APIntStorage : public APNumericStorage { +public: + llvm::APInt getValue() const { return getIntValue(); } + void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } +}; + +class APFloatStorage : public APNumericStorage { +public: + llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); } + void setValue(ASTContext &C, const llvm::APFloat &Val) { + setIntValue(C, Val.bitcastToAPInt()); + } +}; + class IntegerLiteral : public Expr { - llvm::APInt Value; + APIntStorage Num; SourceLocation Loc; + + /// \brief Construct an empty integer literal. + explicit IntegerLiteral(EmptyShell Empty) + : Expr(IntegerLiteralClass, Empty) { } + public: // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy - IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) { + IntegerLiteral(ASTContext &C, const llvm::APInt &V, + QualType type, SourceLocation l) + : Expr(IntegerLiteralClass, type, false, false), Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); + setValue(C, V); } - /// \brief Construct an empty integer literal. - explicit IntegerLiteral(EmptyShell Empty) - : Expr(IntegerLiteralClass, Empty) { } + // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, + // or UnsignedLongLongTy + static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V, + QualType type, SourceLocation l); + static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); - const llvm::APInt &getValue() const { return Value; } + llvm::APInt getValue() const { return Num.getValue(); } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } - void setValue(const llvm::APInt &Val) { Value = Val; } + void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); } void setLocation(SourceLocation Location) { Loc = Location; } static bool classof(const Stmt *T) { @@ -795,21 +883,30 @@ public: }; class FloatingLiteral : public Expr { - llvm::APFloat Value; + APFloatStorage Num; bool IsExact : 1; SourceLocation Loc; -public: - FloatingLiteral(const llvm::APFloat &V, bool isexact, + + FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type, false, false), Value(V), - IsExact(isexact), Loc(L) {} + : Expr(FloatingLiteralClass, Type, false, false), + IsExact(isexact), Loc(L) { + setValue(C, V); + } /// \brief Construct an empty floating-point literal. explicit FloatingLiteral(EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty), Value(0.0) { } + : Expr(FloatingLiteralClass, Empty), IsExact(false) { } - const llvm::APFloat &getValue() const { return Value; } - void setValue(const llvm::APFloat &Val) { Value = Val; } +public: + static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, + bool isexact, QualType Type, SourceLocation L); + static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); + + llvm::APFloat getValue() const { return Num.getValue(); } + void setValue(ASTContext &C, const llvm::APFloat &Val) { + Num.setValue(C, Val); + } bool isExact() const { return IsExact; } void setExact(bool E) { IsExact = E; } @@ -889,9 +986,6 @@ class StringLiteral : public Expr { StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {} -protected: - virtual void DoDestroy(ASTContext &C); - public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. @@ -912,8 +1006,7 @@ public: llvm::StringRef getString() const { return llvm::StringRef(StrData, ByteLength); } - // FIXME: These are deprecated, replace with StringRef. - const char *getStrData() const { return StrData; } + unsigned getByteLength() const { return ByteLength; } /// \brief Sets the string data to the given string data. @@ -1009,40 +1102,27 @@ public: /// applied to a non-complex value, the former returns its operand and the /// later returns zero in the type of the operand. /// -/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose -/// subexpression is a compound literal with the various MemberExpr and -/// ArraySubscriptExpr's applied to it. (This is only used in C) -/// class UnaryOperator : public Expr { public: - // Note that additions to this should also update the StmtVisitor class. - enum Opcode { - PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators - PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators. - AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators. - Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators. - Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators. - Real, Imag, // "__real expr"/"__imag expr" Extension. - Extension, // __extension__ marker. - OffsetOf // __builtin_offsetof - }; + typedef UnaryOperatorKind Opcode; + private: - Stmt *Val; - Opcode Opc; + unsigned Opc : 5; SourceLocation Loc; + Stmt *Val; public: UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) : Expr(UnaryOperatorClass, type, - input->isTypeDependent() && opc != OffsetOf, + input->isTypeDependent() || type->isDependentType(), input->isValueDependent()), - Val(input), Opc(opc), Loc(l) {} + Opc(opc), Loc(l), Val(input) {} /// \brief Build an empty unary operator. explicit UnaryOperator(EmptyShell Empty) - : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { } + : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } - Opcode getOpcode() const { return Opc; } + Opcode getOpcode() const { return static_cast<Opcode>(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getSubExpr() const { return cast<Expr>(Val); } @@ -1054,21 +1134,26 @@ public: /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { - return Op == PostInc || Op == PostDec; + return Op == UO_PostInc || Op == UO_PostDec; } /// isPostfix - Return true if this is a prefix operation, like --x. static bool isPrefix(Opcode Op) { - return Op == PreInc || Op == PreDec; + return Op == UO_PreInc || Op == UO_PreDec; } - bool isPrefix() const { return isPrefix(Opc); } - bool isPostfix() const { return isPostfix(Opc); } - bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; } - bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } - bool isOffsetOfOp() const { return Opc == OffsetOf; } - static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } - bool isArithmeticOp() const { return isArithmeticOp(Opc); } + bool isPrefix() const { return isPrefix(getOpcode()); } + bool isPostfix() const { return isPostfix(getOpcode()); } + bool isIncrementOp() const { + return Opc == UO_PreInc || Opc == UO_PostInc; + } + bool isIncrementDecrementOp() const { + return Opc <= UO_PreDec; + } + static bool isArithmeticOp(Opcode Op) { + return Op >= UO_Plus && Op <= UO_LNot; + } + bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); } /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++" @@ -1310,9 +1395,6 @@ class SizeOfAlignOfExpr : public Expr { } Argument; SourceLocation OpLoc, RParenLoc; -protected: - virtual void DoDestroy(ASTContext& C); - public: SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, QualType resultType, SourceLocation op, @@ -1485,8 +1567,6 @@ protected: CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); - virtual void DoDestroy(ASTContext& C); - public: CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc); @@ -1494,8 +1574,6 @@ public: /// \brief Build an empty call expression. CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); - ~CallExpr() {} - const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } void setCallee(Expr *F) { SubExprs[FN] = F; } @@ -1594,6 +1672,10 @@ class MemberExpr : public Expr { /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; + /// MemberDNLoc - Provides source/type location info for the + /// declaration name embedded in MemberDecl. + DeclarationNameLoc MemberDNLoc; + /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow : 1; @@ -1621,37 +1703,33 @@ class MemberExpr : public Expr { return const_cast<MemberExpr *>(this)->getMemberQualifier(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - if (!HasExplicitTemplateArgumentList) - return 0; - - if (!HasQualifierOrFoundDecl) - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return reinterpret_cast<ExplicitTemplateArgumentList *>( - getMemberQualifier() + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList(); +public: + MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, + const DeclarationNameInfo &NameInfo, QualType ty) + : Expr(MemberExprClass, ty, + base->isTypeDependent(), base->isValueDependent()), + Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), + MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) { + assert(memberdecl->getDeclName() == NameInfo.getName()); } -public: + // NOTE: this constructor should be used only when it is known that + // the member name can not provide additional syntactic info + // (i.e., source locations for C++ operator names or type source info + // for constructors, destructors and conversion oeprators). MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, SourceLocation l, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), + IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, ValueDecl *memberdecl, DeclAccessPair founddecl, - SourceLocation l, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, QualType ty); @@ -1700,15 +1778,42 @@ public: /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() const { + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgumentList; } /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgumentList()) - getExplicitTemplateArgumentList()->copyInto(List); + if (hasExplicitTemplateArgs()) + getExplicitTemplateArgs().copyInto(List); + } + + /// \brief Retrieve the explicit template argument list that + /// follow the member template name. This must only be called on an + /// expression with explicit template arguments. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(HasExplicitTemplateArgumentList); + if (!HasQualifierOrFoundDecl) + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + getMemberQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that + /// followed the member template name. This must only be called on + /// an expression with explicit template arguments. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs(); + } + + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } /// \brief Retrieve the location of the left angle bracket following the @@ -1717,7 +1822,7 @@ public: if (!HasExplicitTemplateArgumentList) return SourceLocation(); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this @@ -1726,7 +1831,7 @@ public: if (!HasExplicitTemplateArgumentList) return 0; - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this @@ -1735,7 +1840,7 @@ public: if (!HasExplicitTemplateArgumentList) return 0; - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the @@ -1744,7 +1849,13 @@ public: if (!HasExplicitTemplateArgumentList) return SourceLocation(); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; + } + + /// \brief Retrieve the member declaration name info. + DeclarationNameInfo getMemberNameInfo() const { + return DeclarationNameInfo(MemberDecl->getDeclName(), + MemberLoc, MemberDNLoc); } bool isArrow() const { return IsArrow; } @@ -1758,9 +1869,8 @@ public: virtual SourceRange getSourceRange() const { // If we have an implicit base (like a C++ implicit this), // make sure not to return its location - SourceLocation EndLoc = MemberLoc; - if (HasExplicitTemplateArgumentList) - EndLoc = getRAngleLoc(); + SourceLocation EndLoc = (HasExplicitTemplateArgumentList) + ? getRAngleLoc() : getMemberNameInfo().getEndLoc(); SourceLocation BaseLoc = getBase()->getLocStart(); if (BaseLoc.isInvalid()) @@ -1843,110 +1953,13 @@ public: /// classes). class CastExpr : public Expr { public: - /// CastKind - the kind of cast this represents. - enum CastKind { - /// CK_Unknown - Unknown cast kind. - /// FIXME: The goal is to get rid of this and make all casts have a - /// kind so that the AST client doesn't have to try to figure out what's - /// going on. - CK_Unknown, - - /// CK_BitCast - Used for reinterpret_cast. - CK_BitCast, - - /// CK_LValueBitCast - Used for reinterpret_cast of expressions to - /// a reference type. - CK_LValueBitCast, - - /// CK_NoOp - Used for const_cast. - CK_NoOp, - - /// CK_BaseToDerived - Base to derived class casts. - CK_BaseToDerived, - - /// CK_DerivedToBase - Derived to base class casts. - CK_DerivedToBase, - - /// CK_UncheckedDerivedToBase - Derived to base class casts that - /// assume that the derived pointer is not null. - CK_UncheckedDerivedToBase, - - /// CK_Dynamic - Dynamic cast. - CK_Dynamic, - - /// CK_ToUnion - Cast to union (GCC extension). - CK_ToUnion, - - /// CK_ArrayToPointerDecay - Array to pointer decay. - CK_ArrayToPointerDecay, - - // CK_FunctionToPointerDecay - Function to pointer decay. - CK_FunctionToPointerDecay, - - /// CK_NullToMemberPointer - Null pointer to member pointer. - CK_NullToMemberPointer, - - /// CK_BaseToDerivedMemberPointer - Member pointer in base class to - /// member pointer in derived class. - CK_BaseToDerivedMemberPointer, - - /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to - /// member pointer in base class. - CK_DerivedToBaseMemberPointer, - - /// CK_UserDefinedConversion - Conversion using a user defined type - /// conversion function. - CK_UserDefinedConversion, - - /// CK_ConstructorConversion - Conversion by constructor - CK_ConstructorConversion, - - /// CK_IntegralToPointer - Integral to pointer - CK_IntegralToPointer, - - /// CK_PointerToIntegral - Pointer to integral - CK_PointerToIntegral, - - /// CK_ToVoid - Cast to void. - CK_ToVoid, - - /// CK_VectorSplat - Casting from an integer/floating type to an extended - /// vector type with the same element type as the src type. Splats the - /// src expression into the destination expression. - CK_VectorSplat, - - /// CK_IntegralCast - Casting between integral types of different size. - CK_IntegralCast, - - /// CK_IntegralToFloating - Integral to floating point. - CK_IntegralToFloating, - - /// CK_FloatingToIntegral - Floating point to integral. - CK_FloatingToIntegral, - - /// CK_FloatingCast - Casting between floating types of different size. - CK_FloatingCast, - - /// CK_MemberPointerToBoolean - Member pointer to boolean - CK_MemberPointerToBoolean, - - /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c - /// pointer - CK_AnyPointerToObjCPointerCast, - /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block - /// pointer - CK_AnyPointerToBlockPointerCast - - }; + typedef clang::CastKind CastKind; private: - CastKind Kind; + unsigned Kind : 5; + unsigned BasePathSize : BitsRemaining - 5; Stmt *Op; - /// BasePath - For derived-to-base and base-to-derived casts, the base array - /// contains the inheritance path. - CXXBaseSpecifierArray BasePath; - void CheckBasePath() const { #ifndef NDEBUG switch (getCastKind()) { @@ -1955,7 +1968,7 @@ private: case CK_DerivedToBaseMemberPointer: case CK_BaseToDerived: case CK_BaseToDerivedMemberPointer: - assert(!BasePath.empty() && "Cast kind should have a base path!"); + assert(!path_empty() && "Cast kind should have a base path!"); break; // These should not have an inheritance path. @@ -1981,15 +1994,21 @@ private: case CK_MemberPointerToBoolean: case CK_AnyPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: - assert(BasePath.empty() && "Cast kind should not have a base path!"); + case CK_ObjCObjectLValueCast: + assert(path_empty() && "Cast kind should not have a base path!"); break; } #endif } + const CXXBaseSpecifier * const *path_buffer() const { + return const_cast<CastExpr*>(this)->path_buffer(); + } + CXXBaseSpecifier **path_buffer(); + protected: CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath) : + unsigned BasePathSize) : Expr(SC, ty, // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). @@ -1997,18 +2016,16 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent())), - Kind(kind), Op(op), BasePath(BasePath) { - CheckBasePath(); - } + Kind(kind), BasePathSize(BasePathSize), Op(op) { + CheckBasePath(); + } /// \brief Construct an empty cast. - CastExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty) { } - - virtual void DoDestroy(ASTContext &C); + CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) + : Expr(SC, Empty), BasePathSize(BasePathSize) { } public: - CastKind getCastKind() const { return Kind; } + CastKind getCastKind() const { return static_cast<CastKind>(Kind); } void setCastKind(CastKind K) { Kind = K; } const char *getCastKindName() const; @@ -2024,8 +2041,16 @@ public: return const_cast<CastExpr *>(this)->getSubExprAsWritten(); } - const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } - CXXBaseSpecifierArray& getBasePath() { return BasePath; } + typedef CXXBaseSpecifier **path_iterator; + typedef const CXXBaseSpecifier * const *path_const_iterator; + bool path_empty() const { return BasePathSize == 0; } + unsigned path_size() const { return BasePathSize; } + path_iterator path_begin() { return path_buffer(); } + path_iterator path_end() { return path_buffer() + path_size(); } + path_const_iterator path_begin() const { return path_buffer(); } + path_const_iterator path_end() const { return path_buffer() + path_size(); } + + void setCastPath(const CXXCastPath &Path); static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCastExprConstant && @@ -2045,38 +2070,57 @@ public: /// /// In C, implicit casts always produce rvalues. However, in C++, an /// implicit cast whose result is being bound to a reference will be -/// an lvalue. For example: +/// an lvalue or xvalue. For example: /// /// @code /// class Base { }; /// class Derived : public Base { }; +/// Derived &&ref(); /// void f(Derived d) { -/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base +/// Base& b = d; // initializer is an ImplicitCastExpr +/// // to an lvalue of type Base +/// Base&& r = ref(); // initializer is an ImplicitCastExpr +/// // to an xvalue of type Base /// } /// @endcode class ImplicitCastExpr : public CastExpr { - /// LvalueCast - Whether this cast produces an lvalue. - bool LvalueCast; +private: + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, + unsigned BasePathLength, ExprValueKind VK) + : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) { + ValueKind = VK; + } + + /// \brief Construct an empty implicit cast. + explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) + : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } public: - ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, bool Lvalue) - : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), - LvalueCast(Lvalue) { } + enum OnStack_t { OnStack }; + ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, + ExprValueKind VK) + : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) { + ValueKind = VK; + } - /// \brief Construct an empty implicit cast. - explicit ImplicitCastExpr(EmptyShell Shell) - : CastExpr(ImplicitCastExprClass, Shell) { } + static ImplicitCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Operand, + const CXXCastPath *BasePath, + ExprValueKind Cat); + + static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); virtual SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); } - /// isLvalueCast - Whether this cast produces an lvalue. - bool isLvalueCast() const { return LvalueCast; } + /// getValueKind - The value kind that this cast produces. + ExprValueKind getValueKind() const { + return static_cast<ExprValueKind>(ValueKind); + } - /// setLvalueCast - Set whether this cast produces an lvalue. - void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; } + /// setValueKind - Set the value kind this cast produces. + void setValueKind(ExprValueKind Cat) { ValueKind = Cat; } static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; @@ -2098,8 +2142,8 @@ public: /// actual type of the expression as determined by semantic /// analysis. These types may differ slightly. For example, in C++ one /// can cast to a reference type, which indicates that the resulting -/// expression will be an lvalue. The reference type, however, will -/// not be used as the type of the expression. +/// expression will be an lvalue or xvalue. The reference type, however, +/// will not be used as the type of the expression. class ExplicitCastExpr : public CastExpr { /// TInfo - Source type info for the (written) type /// this expression is casting to. @@ -2107,13 +2151,12 @@ class ExplicitCastExpr : public CastExpr { protected: ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, - Expr *op, CXXBaseSpecifierArray BasePath, - TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {} + Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {} /// \brief Construct an empty explicit cast. - ExplicitCastExpr(StmtClass SC, EmptyShell Shell) - : CastExpr(SC, Shell) { } + ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) + : CastExpr(SC, Shell, PathSize) { } public: /// getTypeInfoAsWritten - Returns the type source info for the type @@ -2138,16 +2181,24 @@ public: class CStyleCastExpr : public ExplicitCastExpr { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren -public: + CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation r) - : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath, + : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize, writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. - explicit CStyleCastExpr(EmptyShell Shell) - : ExplicitCastExpr(CStyleCastExprClass, Shell) { } + explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } + +public: + static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K, + Expr *Op, const CXXCastPath *BasePath, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation R); + + static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } @@ -2184,33 +2235,14 @@ public: /// be used to express the computation. class BinaryOperator : public Expr { public: - enum Opcode { - // Operators listed in order of precedence. - // Note that additions to this should also update the StmtVisitor class. - PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators. - Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. - Add, Sub, // [C99 6.5.6] Additive operators. - Shl, Shr, // [C99 6.5.7] Bitwise shift operators. - LT, GT, LE, GE, // [C99 6.5.8] Relational operators. - EQ, NE, // [C99 6.5.9] Equality operators. - And, // [C99 6.5.10] Bitwise AND operator. - Xor, // [C99 6.5.11] Bitwise XOR operator. - Or, // [C99 6.5.12] Bitwise OR operator. - LAnd, // [C99 6.5.13] Logical AND operator. - LOr, // [C99 6.5.14] Logical OR operator. - Assign, MulAssign,// [C99 6.5.16] Assignment operators. - DivAssign, RemAssign, - AddAssign, SubAssign, - ShlAssign, ShrAssign, - AndAssign, XorAssign, - OrAssign, - Comma // [C99 6.5.17] Comma operator. - }; + typedef BinaryOperatorKind Opcode; + private: + unsigned Opc : 6; + SourceLocation OpLoc; + enum { LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; - Opcode Opc; - SourceLocation OpLoc; public: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, @@ -2227,12 +2259,12 @@ public: /// \brief Construct an empty binary operator. explicit BinaryOperator(EmptyShell Empty) - : Expr(BinaryOperatorClass, Empty), Opc(Comma) { } + : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } SourceLocation getOperatorLoc() const { return OpLoc; } void setOperatorLoc(SourceLocation L) { OpLoc = L; } - Opcode getOpcode() const { return Opc; } + Opcode getOpcode() const { return static_cast<Opcode>(Opc); } void setOpcode(Opcode O) { Opc = O; } Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } @@ -2248,6 +2280,8 @@ public: /// corresponds to, e.g. "<<=". static const char *getOpcodeStr(Opcode Op); + const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); } + /// \brief Retrieve the binary opcode that corresponds to the given /// overloaded operator. static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); @@ -2257,30 +2291,34 @@ public: static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); /// predicates to categorize the respective opcodes. - bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } - static bool isAdditiveOp(Opcode Opc) { return Opc == Add || Opc == Sub; } - bool isAdditiveOp() const { return isAdditiveOp(Opc); } - static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } - bool isShiftOp() const { return isShiftOp(Opc); } + bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; } + static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } + bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } + static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; } + bool isShiftOp() const { return isShiftOp(getOpcode()); } - static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; } - bool isBitwiseOp() const { return isBitwiseOp(Opc); } + static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; } + bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); } - static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } - bool isRelationalOp() const { return isRelationalOp(Opc); } + static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; } + bool isRelationalOp() const { return isRelationalOp(getOpcode()); } - static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } - bool isEqualityOp() const { return isEqualityOp(Opc); } + static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; } + bool isEqualityOp() const { return isEqualityOp(getOpcode()); } - static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; } - bool isComparisonOp() const { return isComparisonOp(Opc); } + static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } + bool isComparisonOp() const { return isComparisonOp(getOpcode()); } - static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; } - bool isLogicalOp() const { return isLogicalOp(Opc); } + static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } + bool isLogicalOp() const { return isLogicalOp(getOpcode()); } - bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; } - bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;} - bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } + bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; } + bool isCompoundAssignmentOp() const { + return Opc > BO_Assign && Opc <= BO_OrAssign; + } + bool isShiftAssignOp() const { + return Opc == BO_ShlAssign || Opc == BO_ShrAssign; + } static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && @@ -2304,7 +2342,7 @@ protected: } BinaryOperator(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Opc(MulAssign) { } + : Expr(SC, Empty), Opc(BO_MulAssign) { } }; /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep @@ -2353,10 +2391,11 @@ public: class ConditionalOperator : public Expr { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + Stmt* Save; SourceLocation QuestionLoc, ColonLoc; public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - SourceLocation CLoc, Expr *rhs, QualType t) + SourceLocation CLoc, Expr *rhs, Expr *save, QualType t) : Expr(ConditionalOperatorClass, t, // FIXME: the type of the conditional operator doesn't // depend on the type of the conditional, but the standard @@ -2370,6 +2409,7 @@ public: SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; + Save = save; } /// \brief Build an empty conditional operator. @@ -2382,25 +2422,31 @@ public: void setCond(Expr *E) { SubExprs[COND] = E; } // getTrueExpr - Return the subexpression representing the value of the ?: - // expression if the condition evaluates to true. In most cases this value - // will be the same as getLHS() except a GCC extension allows the left - // subexpression to be omitted, and instead of the condition be returned. - // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x" - // is only evaluated once. + // expression if the condition evaluates to true. Expr *getTrueExpr() const { - return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]); + return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]); } - // getTrueExpr - Return the subexpression representing the value of the ?: + // getFalseExpr - Return the subexpression representing the value of the ?: // expression if the condition evaluates to false. This is the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - - Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); } + + // getSaveExpr - In most cases this value will be null. Except a GCC extension + // allows the left subexpression to be omitted, and instead of that condition + // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the + // expression "x" is only evaluated once. Under this senario, this function + // returns the original, non-converted condition expression for the ?:operator + Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; } + + Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } + Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; } + void setSAVE(Expr *E) { Save = E; } + SourceLocation getQuestionLoc() const { return QuestionLoc; } void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } @@ -2500,23 +2546,27 @@ public: /// expressions) are compatible. The result of this built-in function can be /// used in integer constant expressions. class TypesCompatibleExpr : public Expr { - QualType Type1; - QualType Type2; + TypeSourceInfo *TInfo1; + TypeSourceInfo *TInfo2; SourceLocation BuiltinLoc, RParenLoc; public: TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, - QualType t1, QualType t2, SourceLocation RP) : + TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2, + SourceLocation RP) : Expr(TypesCompatibleExprClass, ReturnType, false, false), - Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {} + TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {} /// \brief Build an empty __builtin_type_compatible_p expression. explicit TypesCompatibleExpr(EmptyShell Empty) : Expr(TypesCompatibleExprClass, Empty) { } - QualType getArgType1() const { return Type1; } - void setArgType1(QualType T) { Type1 = T; } - QualType getArgType2() const { return Type2; } - void setArgType2(QualType T) { Type2 = T; } + TypeSourceInfo *getArgTInfo1() const { return TInfo1; } + void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; } + TypeSourceInfo *getArgTInfo2() const { return TInfo2; } + void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; } + + QualType getArgType1() const { return TInfo1->getType(); } + QualType getArgType2() const { return TInfo2->getType(); } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -2553,9 +2603,6 @@ class ShuffleVectorExpr : public Expr { Stmt **SubExprs; unsigned NumExprs; -protected: - virtual void DoDestroy(ASTContext &C); - public: // FIXME: Can a shufflevector be value-dependent? Does type-dependence need // to be computed differently? @@ -2588,8 +2635,6 @@ public: } static bool classof(const ShuffleVectorExpr *) { return true; } - ~ShuffleVectorExpr() {} - /// getNumSubExprs - Return the size of the SubExprs array. This includes the /// constant expression, the actual arguments passed in, and the function /// pointers. @@ -2716,11 +2761,13 @@ public: /// VAArgExpr, used for the builtin function __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; + TypeSourceInfo *TInfo; SourceLocation BuiltinLoc, RParenLoc; public: - VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc) + VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo, + SourceLocation RPLoc, QualType t) : Expr(VAArgExprClass, t, t->isDependentType(), false), - Val(e), + Val(e), TInfo(TInfo), BuiltinLoc(BLoc), RParenLoc(RPLoc) { } @@ -2731,6 +2778,9 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } + TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; } + void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; } + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -2896,12 +2946,18 @@ public: virtual child_iterator child_end(); typedef InitExprsTy::iterator iterator; + typedef InitExprsTy::const_iterator const_iterator; typedef InitExprsTy::reverse_iterator reverse_iterator; + typedef InitExprsTy::const_reverse_iterator const_reverse_iterator; iterator begin() { return InitExprs.begin(); } + const_iterator begin() const { return InitExprs.begin(); } iterator end() { return InitExprs.end(); } + const_iterator end() const { return InitExprs.end(); } reverse_iterator rbegin() { return InitExprs.rbegin(); } + const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } reverse_iterator rend() { return InitExprs.rend(); } + const_reverse_iterator rend() const { return InitExprs.rend(); } }; /// @brief Represents a C99 designated initializer expression. @@ -2961,11 +3017,6 @@ private: : Expr(DesignatedInitExprClass, EmptyShell()), NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } -protected: - virtual void DoDestroy(ASTContext &C); - - void DestroyDesignators(ASTContext &C); - public: /// A field designator, e.g., ".x". struct FieldDesignator { @@ -3233,15 +3284,10 @@ class ParenListExpr : public Expr { unsigned NumExprs; SourceLocation LParenLoc, RParenLoc; -protected: - virtual void DoDestroy(ASTContext& C); - public: ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned numexprs, SourceLocation rparenloc); - ~ParenListExpr() {} - /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -3274,8 +3320,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index b955381..0a94354 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -121,12 +121,12 @@ private: protected: CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} + : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {} - explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) - : ExplicitCastExpr(SC, Shell) { } + explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(SC, Shell, PathSize) { } public: const char *getCastName() const; @@ -158,14 +158,22 @@ public: /// This expression node represents a C++ static cast, e.g., /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { -public: CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize, + writtenTy, l) {} - explicit CXXStaticCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } + explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } + +public: + static CXXStaticCastExpr *Create(ASTContext &Context, QualType T, + CastKind K, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *Written, SourceLocation L); + static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, + unsigned PathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; @@ -180,15 +188,23 @@ public: /// This expression node represents a dynamic cast, e.g., /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { -public: CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize, writtenTy, l) {} - explicit CXXDynamicCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } + explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } + +public: + static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *Written, SourceLocation L); + + static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, + unsigned pathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; @@ -203,15 +219,22 @@ public: /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast<int>(VoidPtr). class CXXReinterpretCastExpr : public CXXNamedCastExpr { -public: CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, - CXXBaseSpecifierArray BasePath, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize, writtenTy, l) {} - explicit CXXReinterpretCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { } + CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } + +public: + static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *WrittenTy, SourceLocation L); + static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, + unsigned pathSize); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; @@ -225,14 +248,18 @@ public: /// This expression node represents a const cast, e.g., /// @c const_cast<char*>(PtrToConstChar). class CXXConstCastExpr : public CXXNamedCastExpr { -public: CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l) : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, - CXXBaseSpecifierArray(), writtenTy, l) {} + 0, writtenTy, l) {} explicit CXXConstCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } + : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } + +public: + static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op, + TypeSourceInfo *WrittenTy, SourceLocation L); + static CXXConstCastExpr *CreateEmpty(ASTContext &Context); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; @@ -479,9 +506,6 @@ class CXXDefaultArgExpr : public Expr { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } -protected: - virtual void DoDestroy(ASTContext &C); - public: CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} @@ -535,8 +559,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; - friend class PCHStmtWriter; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// CXXTemporary - Represents a C++ temporary. @@ -546,14 +570,11 @@ class CXXTemporary { CXXTemporary(const CXXDestructorDecl *destructor) : Destructor(destructor) { } - ~CXXTemporary() { } public: static CXXTemporary *Create(ASTContext &C, const CXXDestructorDecl *Destructor); - void Destroy(ASTContext &Ctx); - const CXXDestructorDecl *getDestructor() const { return Destructor; } }; @@ -579,10 +600,6 @@ class CXXBindTemporaryExpr : public Expr { CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), Temp(temp), SubExpr(subexpr) { } - ~CXXBindTemporaryExpr() { } - -protected: - virtual void DoDestroy(ASTContext &C); public: CXXBindTemporaryExpr(EmptyShell Empty) @@ -614,73 +631,6 @@ public: virtual child_iterator child_end(); }; -/// CXXBindReferenceExpr - Represents binding an expression to a reference. -/// In the example: -/// -/// const int &i = 10; -/// -/// a bind reference expression is inserted to indicate that 10 is bound to -/// a reference, and that a temporary needs to be created to hold the -/// value. -class CXXBindReferenceExpr : public Expr { - // SubExpr - The expression being bound. - Stmt *SubExpr; - - // ExtendsLifetime - Whether binding this reference extends the lifetime of - // the expression being bound. FIXME: Add C++ reference. - bool ExtendsLifetime; - - /// RequiresTemporaryCopy - Whether binding the subexpression requires a - /// temporary copy. - bool RequiresTemporaryCopy; - - CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime, - bool RequiresTemporaryCopy) - : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false), - SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime), - RequiresTemporaryCopy(RequiresTemporaryCopy) { } - ~CXXBindReferenceExpr() { } - -protected: - virtual void DoDestroy(ASTContext &C); - -public: - static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr, - bool ExtendsLifetime, - bool RequiresTemporaryCopy); - - explicit CXXBindReferenceExpr(EmptyShell Empty) - : Expr(CXXBindReferenceExprClass, Empty) { } - - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - void setSubExpr(Expr *E) { SubExpr = E; } - - virtual SourceRange getSourceRange() const { - return SubExpr->getSourceRange(); - } - - /// requiresTemporaryCopy - Whether binding the subexpression requires a - /// temporary copy. - bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; } - - // extendsLifetime - Whether binding this reference extends the lifetime of - // the expression being bound. FIXME: Add C++ reference. - bool extendsLifetime() const { return ExtendsLifetime; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXBindReferenceExprClass; - } - static bool classof(const CXXBindReferenceExpr *) { return true; } - - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); - - friend class PCHStmtReader; -}; - /// CXXConstructExpr - Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { public: @@ -707,15 +657,12 @@ protected: Expr **args, unsigned numargs, bool ZeroInitialization = false, ConstructionKind ConstructKind = CK_Complete); - ~CXXConstructExpr() { } /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0), ConstructKind(0), Args(0), NumArgs(0) { } - virtual void DoDestroy(ASTContext &C); - public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) @@ -796,7 +743,7 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// CXXFunctionalCastExpr - Represents an explicit C++ type conversion @@ -805,17 +752,27 @@ public: class CXXFunctionalCastExpr : public ExplicitCastExpr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; -public: + CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, CXXBaseSpecifierArray BasePath, + Expr *castExpr, unsigned pathSize, SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, - BasePath, writtenTy), + pathSize, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} - explicit CXXFunctionalCastExpr(EmptyShell Shell) - : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { } + explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } + +public: + static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, + TypeSourceInfo *Written, + SourceLocation TyBeginLoc, + CastKind Kind, Expr *Op, + const CXXCastPath *Path, + SourceLocation RPLoc); + static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context, + unsigned PathSize); SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } @@ -859,8 +816,6 @@ public: explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { } - ~CXXTemporaryObjectExpr() { } - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -872,7 +827,7 @@ public: } static bool classof(const CXXTemporaryObjectExpr *) { return true; } - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// CXXScalarValueInitExpr - [C++ 5.2.3p2] @@ -952,7 +907,7 @@ class CXXNewExpr : public Expr { SourceLocation StartLoc; SourceLocation EndLoc; - friend class PCHStmtReader; + friend class ASTStmtReader; public: CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs, @@ -967,8 +922,6 @@ public: void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, unsigned numConsArgs); - virtual void DoDestroy(ASTContext &C); - QualType getAllocatedType() const { assert(getType()->isPointerType()); return getType()->getAs<PointerType>()->getPointeeType(); @@ -1381,7 +1334,7 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - friend class PCHStmtReader; + friend class ASTStmtReader; }; /// \brief A reference to an overloaded function set, either an @@ -1395,7 +1348,7 @@ class OverloadExpr : public Expr { unsigned NumResults; /// The common name of these declarations. - DeclarationName Name; + DeclarationNameInfo NameInfo; /// The scope specifier, if any. NestedNameSpecifier *Qualifier; @@ -1403,16 +1356,13 @@ class OverloadExpr : public Expr { /// The source range of the scope specifier. SourceRange QualifierRange; - /// The location of the name. - SourceLocation NameLoc; - protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool HasTemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -1427,19 +1377,38 @@ public: UnresolvedSetIterator End, const TemplateArgumentListInfo *Args); + struct FindResult { + OverloadExpr *Expression; + bool IsAddressOfOperand; + bool HasFormOfMemberPointer; + }; + /// Finds the overloaded expression in the given expression of /// OverloadTy. /// - /// \return the expression (which must be there) and true if it is - /// within an address-of operator. - static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) { + /// \return the expression (which must be there) and true if it has + /// the particular form of a member pointer expression + static FindResult find(Expr *E) { assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); - bool op = false; + FindResult Result; + E = E->IgnoreParens(); - if (isa<UnaryOperator>(E)) - op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); - return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); + if (isa<UnaryOperator>(E)) { + assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); + E = cast<UnaryOperator>(E)->getSubExpr(); + OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens()); + + Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); + Result.IsAddressOfOperand = true; + Result.Expression = Ovl; + } else { + Result.HasFormOfMemberPointer = false; + Result.IsAddressOfOperand = false; + Result.Expression = cast<OverloadExpr>(E); + } + + return Result; } /// Gets the naming class of this lookup, if any. @@ -1457,13 +1426,17 @@ public: /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } + /// Gets the full name info. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } + /// Gets the name looked up. - DeclarationName getName() const { return Name; } - void setName(DeclarationName N) { Name = N; } + DeclarationName getName() const { return NameInfo.getName(); } + void setName(DeclarationName N) { NameInfo.setName(N); } /// Gets the location of the name. - SourceLocation getNameLoc() const { return NameLoc; } - void setNameLoc(SourceLocation Loc) { NameLoc = Loc; } + SourceLocation getNameLoc() const { return NameInfo.getLoc(); } + void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); } /// Fetches the nested-name qualifier, if one was given. NestedNameSpecifier *getQualifier() const { return Qualifier; } @@ -1483,10 +1456,12 @@ public: return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); } - ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { - if (hasExplicitTemplateArgs()) - return &getExplicitTemplateArgs(); - return 0; + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } static bool classof(const Stmt *T) { @@ -1526,11 +1501,11 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, bool HasTemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, - QRange, Name, NameLoc, HasTemplateArgs, Begin, End), + QRange, NameInfo, HasTemplateArgs, Begin, End), RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} @@ -1545,16 +1520,15 @@ public: CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { return new(C) UnresolvedLookupExpr(C, Dependent ? C.DependentTy : C.OverloadTy, Dependent, NamingClass, - Qualifier, QualifierRange, - Name, NameLoc, ADL, Overloaded, false, + Qualifier, QualifierRange, NameInfo, + ADL, Overloaded, false, Begin, End); } @@ -1563,8 +1537,7 @@ public: CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, UnresolvedSetIterator Begin, @@ -1603,6 +1576,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -1626,7 +1607,7 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range(getNameLoc()); + SourceRange Range(getNameInfo().getSourceRange()); if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; @@ -1657,10 +1638,7 @@ public: /// declaration can be found. class DependentScopeDeclRefExpr : public Expr { /// The name of the entity we will be referencing. - DeclarationName Name; - - /// Location of the name of the declaration we're referencing. - SourceLocation Loc; + DeclarationNameInfo NameInfo; /// QualifierRange - The source range that covers the /// nested-name-specifier. @@ -1676,12 +1654,10 @@ class DependentScopeDeclRefExpr : public Expr { DependentScopeDeclRefExpr(QualType T, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool HasExplicitTemplateArgs) : Expr(DependentScopeDeclRefExprClass, T, true, true), - Name(Name), Loc(NameLoc), - QualifierRange(QualifierRange), Qualifier(Qualifier), + NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {} @@ -1689,20 +1665,23 @@ public: static DependentScopeDeclRefExpr *Create(ASTContext &C, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs = 0); static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); /// \brief Retrieve the name that this expression refers to. - DeclarationName getDeclName() const { return Name; } - void setDeclName(DeclarationName N) { Name = N; } + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } + + /// \brief Retrieve the name that this expression refers to. + DeclarationName getDeclName() const { return NameInfo.getName(); } + void setDeclName(DeclarationName N) { NameInfo.setName(N); } /// \brief Retrieve the location of the name within the expression. - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + SourceLocation getLocation() const { return NameInfo.getLoc(); } + void setLocation(SourceLocation L) { NameInfo.setLoc(L); } /// \brief Retrieve the source range of the nested-name-specifier. SourceRange getQualifierRange() const { return QualifierRange; } @@ -1731,6 +1710,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -1777,10 +1764,6 @@ class CXXExprWithTemporaries : public Expr { CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); - ~CXXExprWithTemporaries(); - -protected: - virtual void DoDestroy(ASTContext &C); public: CXXExprWithTemporaries(EmptyShell Empty) @@ -1991,10 +1974,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. /// FIXME: could also be a template-id - DeclarationName Member; - - /// \brief The location of the member name. - SourceLocation MemberLoc; + DeclarationNameInfo MemberNameInfo; CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, @@ -2002,8 +1982,7 @@ class CXXDependentScopeMemberExpr : public Expr { NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); public: @@ -2014,14 +1993,13 @@ public: NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc) + DeclarationNameInfo MemberNameInfo) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), - Member(Member), MemberLoc(MemberLoc) { } + MemberNameInfo(MemberNameInfo) { } static CXXDependentScopeMemberExpr * Create(ASTContext &C, @@ -2030,8 +2008,7 @@ public: NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *FirstQualifierFoundInScope, - DeclarationName Member, - SourceLocation MemberLoc, + DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * @@ -2092,13 +2069,20 @@ public: /// \brief Retrieve the name of the member that this expression /// refers to. - DeclarationName getMember() const { return Member; } - void setMember(DeclarationName N) { Member = N; } + const DeclarationNameInfo &getMemberNameInfo() const { + return MemberNameInfo; + } + void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; } + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMember() const { return MemberNameInfo.getName(); } + void setMember(DeclarationName N) { MemberNameInfo.setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. - SourceLocation getMemberLoc() const { return MemberLoc; } - void setMemberLoc(SourceLocation L) { MemberLoc = L; } + SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } + void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); } /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. @@ -2108,57 +2092,59 @@ public: /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { assert(HasExplicitTemplateArgs); - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); } /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { return const_cast<CXXDependentScopeMemberExpr *>(this) - ->getExplicitTemplateArgumentList(); + ->getExplicitTemplateArgs(); + } + + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); } /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - assert(HasExplicitTemplateArgs); - getExplicitTemplateArgumentList()->copyInto(List); + getExplicitTemplateArgs().copyInto(List); } /// \brief Initializes the template arguments using the given structure. void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { - assert(HasExplicitTemplateArgs); - getExplicitTemplateArgumentList()->initializeFrom(List); + getExplicitTemplateArgs().initializeFrom(List); } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->LAngleLoc; + return getExplicitTemplateArgs().LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->getTemplateArgs(); + return getExplicitTemplateArgs().getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->NumTemplateArgs; + return getExplicitTemplateArgs().NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { - assert(HasExplicitTemplateArgs); - return getExplicitTemplateArgumentList()->RAngleLoc; + return getExplicitTemplateArgs().RAngleLoc; } virtual SourceRange getSourceRange() const { @@ -2168,12 +2154,12 @@ public: else if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); else - Range.setBegin(MemberLoc); + Range.setBegin(MemberNameInfo.getBeginLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); else - Range.setEnd(MemberLoc); + Range.setEnd(MemberNameInfo.getEndLoc()); return Range; } @@ -2226,8 +2212,7 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Member, - SourceLocation MemberLoc, + const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2242,8 +2227,7 @@ public: SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - DeclarationName Member, - SourceLocation MemberLoc, + const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2287,6 +2271,11 @@ public: /// \brief Retrieves the naming class of this lookup. CXXRecordDecl *getNamingClass() const; + /// \brief Retrieve the full name info for the member that this expression + /// refers to. + const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } + void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); } + /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMemberName() const { return getName(); } @@ -2311,6 +2300,14 @@ public: return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1); } + /// \brief Retrieves the optional explicit template arguments. + /// This points to the same data as getExplicitTemplateArgs(), but + /// returns null if there are no explicit template arguments. + const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (!hasExplicitTemplateArgs()) return 0; + return &getExplicitTemplateArgs(); + } + /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { getExplicitTemplateArgs().copyInto(List); @@ -2341,18 +2338,14 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range; + SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); - else - Range.setBegin(getMemberLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); - else - Range.setEnd(getMemberLoc()); return Range; } diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index def9ced..a8ef005 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -14,31 +14,25 @@ #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Type.h" -#include "llvm/ADT/SmallVector.h" #include <cassert> #include <vector> + +namespace llvm { +template <class T> class SmallVectorImpl; +} + namespace clang { class ASTConsumer; class Decl; class DeclContext; +class DeclContextLookupResult; +class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting +class NamedDecl; +class Selector; class Stmt; -/// \brief The deserialized representation of a set of declarations -/// with the same name that are visible in a given context. -struct VisibleDeclaration { - /// \brief The name of the declarations. - DeclarationName Name; - - /// \brief The ID numbers of all of the declarations with this name. - /// - /// These declarations have not necessarily been de-serialized. - llvm::SmallVector<unsigned, 4> Declarations; -}; - /// \brief Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some @@ -58,6 +52,20 @@ public: virtual ~ExternalASTSource(); + /// \brief RAII class for safely pairing a StartedDeserializing call + /// with FinishedDeserializing. + class Deserializing { + ExternalASTSource *Source; + public: + explicit Deserializing(ExternalASTSource *source) : Source(source) { + assert(Source); + Source->StartedDeserializing(); + } + ~Deserializing() { + Source->FinishedDeserializing(); + } + }; + /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. /// @@ -89,10 +97,18 @@ public: /// Generally the final step of this method is either to call /// SetExternalVisibleDeclsForName or to recursively call lookup on /// the DeclContext after calling SetExternalVisibleDecls. - virtual DeclContext::lookup_result + virtual DeclContextLookupResult FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) = 0; + /// \brief Deserialize all the visible declarations from external storage. + /// + /// Name lookup deserializes visible declarations lazily, thus a DeclContext + /// may not have a complete name lookup table. This function deserializes + /// the rest of visible declarations from the external storage and completes + /// the name lookup table of the DeclContext. + virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0; + /// \brief Finds all declarations lexically contained within the given /// DeclContext. /// @@ -100,6 +116,19 @@ public: virtual bool FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Result) = 0; + /// \brief Notify ExternalASTSource that we started deserialization of + /// a decl or type so until FinishedDeserializing is called there may be + /// decls that are initializing. Must be paired with FinishedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void StartedDeserializing() { } + + /// \brief Notify ExternalASTSource that we finished the deserialization of + /// a decl or type. Must be paired with StartedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void FinishedDeserializing() { } + /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// @@ -113,30 +142,18 @@ public: virtual void PrintStats(); protected: - /// \brief Initialize the context's lookup map with the given decls. - /// It is assumed that none of the declarations are redeclarations of - /// each other. - static void SetExternalVisibleDecls(const DeclContext *DC, - const llvm::SmallVectorImpl<VisibleDeclaration> &Decls); - - /// \brief Initialize the context's lookup map with the given decls. - /// It is assumed that none of the declarations are redeclarations of - /// each other. - static void SetExternalVisibleDecls(const DeclContext *DC, - const llvm::SmallVectorImpl<NamedDecl*> &Decls); - - static DeclContext::lookup_result - SetExternalVisibleDeclsForName(const DeclContext *DC, - const VisibleDeclaration &VD); - - static DeclContext::lookup_result + static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, llvm::SmallVectorImpl<NamedDecl*> &Decls); - static DeclContext::lookup_result + static DeclContextLookupResult SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); + + void MaterializeVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -145,7 +162,7 @@ protected: /// The AST node is identified within the external AST source by a /// 63-bit offset, and can be retrieved via an operation on the /// external AST source itself. -template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)> +template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> struct LazyOffsetPtr { /// \brief Either a pointer to an AST node or the offset within the /// external AST source where the AST node can be found. @@ -203,9 +220,13 @@ public: }; /// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt> +typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> LazyDeclStmtPtr; +/// \brief A lazy pointer to a declaration. +typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> + LazyDeclPtr; + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h index bb81bf0..6ceefed 100644 --- a/include/clang/AST/FullExpr.h +++ b/include/clang/AST/FullExpr.h @@ -47,7 +47,6 @@ class FullExpr { public: static FullExpr Create(ASTContext &Context, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); - void Destroy(ASTContext &Context); Expr *getExpr() { if (Expr *E = SubExpr.dyn_cast<Expr *>()) diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index 00a1e1b..6ba6e89 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,6 +1,6 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc +BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ $(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ -I $(PROJ_SRC_DIR)/../../ $< +$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang attribute implementations with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< + $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \ $(ObjDir)/.dir $(Echo) "Building Clang statement node tables with tblgen" diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 1594b09..3b25f3b 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -181,8 +181,6 @@ public: ID.AddPointer(Specifier); } - void Destroy(ASTContext &Context); - /// \brief Dump the nested name specifier to standard output to aid /// in debugging. void dump(const LangOptions &LO); diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h new file mode 100644 index 0000000..8045311 --- /dev/null +++ b/include/clang/AST/OperationKinds.h @@ -0,0 +1,158 @@ +//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates the different kinds of operations that can be +// performed by various expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H +#define LLVM_CLANG_AST_OPERATION_KINDS_H + +namespace clang { + +/// CastKind - the kind of cast this represents. +enum CastKind { + /// CK_Unknown - Unknown cast kind. + /// FIXME: The goal is to get rid of this and make all casts have a + /// kind so that the AST client doesn't have to try to figure out what's + /// going on. + CK_Unknown, + + /// CK_BitCast - Used for reinterpret_cast. + CK_BitCast, + + /// CK_LValueBitCast - Used for reinterpret_cast of expressions to + /// a reference type. + CK_LValueBitCast, + + /// CK_NoOp - Used for const_cast. + CK_NoOp, + + /// CK_BaseToDerived - Base to derived class casts. + CK_BaseToDerived, + + /// CK_DerivedToBase - Derived to base class casts. + CK_DerivedToBase, + + /// CK_UncheckedDerivedToBase - Derived to base class casts that + /// assume that the derived pointer is not null. + CK_UncheckedDerivedToBase, + + /// CK_Dynamic - Dynamic cast. + CK_Dynamic, + + /// CK_ToUnion - Cast to union (GCC extension). + CK_ToUnion, + + /// CK_ArrayToPointerDecay - Array to pointer decay. + CK_ArrayToPointerDecay, + + // CK_FunctionToPointerDecay - Function to pointer decay. + CK_FunctionToPointerDecay, + + /// CK_NullToMemberPointer - Null pointer to member pointer. + CK_NullToMemberPointer, + + /// CK_BaseToDerivedMemberPointer - Member pointer in base class to + /// member pointer in derived class. + CK_BaseToDerivedMemberPointer, + + /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to + /// member pointer in base class. + CK_DerivedToBaseMemberPointer, + + /// CK_UserDefinedConversion - Conversion using a user defined type + /// conversion function. + CK_UserDefinedConversion, + + /// CK_ConstructorConversion - Conversion by constructor + CK_ConstructorConversion, + + /// CK_IntegralToPointer - Integral to pointer + CK_IntegralToPointer, + + /// CK_PointerToIntegral - Pointer to integral + CK_PointerToIntegral, + + /// CK_ToVoid - Cast to void. + CK_ToVoid, + + /// CK_VectorSplat - Casting from an integer/floating type to an extended + /// vector type with the same element type as the src type. Splats the + /// src expression into the destination expression. + CK_VectorSplat, + + /// CK_IntegralCast - Casting between integral types of different size. + CK_IntegralCast, + + /// CK_IntegralToFloating - Integral to floating point. + CK_IntegralToFloating, + + /// CK_FloatingToIntegral - Floating point to integral. + CK_FloatingToIntegral, + + /// CK_FloatingCast - Casting between floating types of different size. + CK_FloatingCast, + + /// CK_MemberPointerToBoolean - Member pointer to boolean + CK_MemberPointerToBoolean, + + /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c + /// pointer + CK_AnyPointerToObjCPointerCast, + + /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block + /// pointer + CK_AnyPointerToBlockPointerCast, + + /// \brief Converting between two Objective-C object types, which + /// can occur when performing reference binding to an Objective-C + /// object. + CK_ObjCObjectLValueCast +}; + + +enum BinaryOperatorKind { + // Operators listed in order of precedence. + // Note that additions to this should also update the StmtVisitor class. + BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. + BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. + BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. + BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. + BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. + BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. + BO_And, // [C99 6.5.10] Bitwise AND operator. + BO_Xor, // [C99 6.5.11] Bitwise XOR operator. + BO_Or, // [C99 6.5.12] Bitwise OR operator. + BO_LAnd, // [C99 6.5.13] Logical AND operator. + BO_LOr, // [C99 6.5.14] Logical OR operator. + BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. + BO_DivAssign, BO_RemAssign, + BO_AddAssign, BO_SubAssign, + BO_ShlAssign, BO_ShrAssign, + BO_AndAssign, BO_XorAssign, + BO_OrAssign, + BO_Comma // [C99 6.5.17] Comma operator. +}; + +enum UnaryOperatorKind { + // Note that additions to this should also update the StmtVisitor class. + UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement + UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement + UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection + UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic + UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic + UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension. + UO_Extension // __extension__ marker. +}; + +} + +#endif diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 0853ddd..232e47b 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -42,7 +42,7 @@ OPERATOR(Plus) OPERATOR(Minus) \ OPERATOR(Not) OPERATOR(LNot) \ OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) OPERATOR(OffsetOf) + OPERATOR(Extension) // All binary operators (excluding compound assign operators). #define BINOP_LIST() \ @@ -123,12 +123,27 @@ namespace clang { /// users may override Traverse* and WalkUpFrom* to implement custom /// traversal strategies. Returning false from one of these overridden /// functions will abort the entire traversal. +/// +/// By default, this visitor tries to visit every part of the explicit +/// source code exactly once. The default policy towards templates +/// is to descend into the 'pattern' class or function body, not any +/// explicit or implicit instantiations. Explicit specializations +/// are still visited, and the patterns of partial specializations +/// are visited separately. This behavior can be changed by +/// overriding shouldVisitTemplateInstantiations() in the derived class +/// to return true, in which case all known implicit and explicit +/// instantiations will be visited at the same time as the pattern +/// from which they were produced. template<typename Derived> class RecursiveASTVisitor { public: /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast<Derived*>(this); } + /// \brief Return whether this visitor should recurse into + /// template instantiations. + bool shouldVisitTemplateInstantiations() const { return false; } + /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// @@ -351,8 +366,11 @@ public: private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, + bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern); + bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ; + bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); + bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseRecordHelper(RecordDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D); @@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { #define OPERATOR(NAME) \ - case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); + case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); BINOP_LIST() #undef OPERATOR #undef BINOP_LIST #define OPERATOR(NAME) \ - case BinaryOperator::NAME##Assign: \ + case BO_##NAME##Assign: \ DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S); CAO_LIST() @@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { #define OPERATOR(NAME) \ - case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S); + case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S); UNARYOP_LIST() #undef OPERATOR @@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( return true; case TemplateArgument::Type: { - TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo(); - return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); + // FIXME: how can TSI ever be NULL? + if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) + return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); + else + return true; } case TemplateArgument::Template: @@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { + // This isn't available for ArrayType, but is for the ArrayTypeLoc. + TRY_TO(TraverseStmt(TL.getSizeExpr())); + return true; +} + DEF_TRAVERSE_TYPELOC(ConstantArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(VariableArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + return TraverseArrayTypeLocHelper(TL); }) DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + return TraverseArrayTypeLocHelper(TL); }) // FIXME: order? why not size expr first? @@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( return true; } +// A helper method for traversing the implicit instantiations of a +// class. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( + ClassTemplateDecl* D, Decl *Pattern) { + assert(isa<ClassTemplateDecl>(Pattern) || + isa<ClassTemplatePartialSpecializationDecl>(Pattern)); + + ClassTemplateDecl::spec_iterator end = D->spec_end(); + for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + ClassTemplateSpecializationDecl* SD = *it; + + switch (SD->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_ImplicitInstantiation: { + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> U + = SD->getInstantiatedFrom(); + + bool ShouldVisit; + if (U.is<ClassTemplateDecl*>()) + ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern); + else + ShouldVisit + = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern); + + if (ShouldVisit) + TRY_TO(TraverseClassTemplateSpecializationDecl(SD)); + break; + } + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + + // We don't need to do anything for an uninstantiated + // specialization. + case TSK_Undeclared: + break; + } + } + + return true; +} + DEF_TRAVERSE_DECL(ClassTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); + CXXRecordDecl* TempDecl = D->getTemplatedDecl(); + TRY_TO(TraverseDecl(TempDecl)); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - // We should not traverse the specializations/partial - // specializations. Those will show up in other contexts. - // getInstantiatedFromMemberTemplate() is just a link from a - // template instantiation back to the template from which it was - // instantiated, and thus should not be traversed either. + + // By default, we do not traverse the instantiations of + // class templates since they do not apprear in the user code. The + // following code optionally traverses them. + if (getDerived().shouldVisitTemplateInstantiations()) { + // If this is the definition of the primary template, visit + // instantiations which were formed from this pattern. + if (D->isThisDeclarationADefinition()) + TRY_TO(TraverseClassInstantiations(D, D)); + } + + // Note that getInstantiatedFromMemberTemplate() is just a link + // from a template instantiation back to the template from which + // it was instantiated, and thus should not be traversed. }) +// A helper method for traversing the instantiations of a +// function while skipping its specializations. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( + FunctionTemplateDecl* D) { + FunctionTemplateDecl::spec_iterator end = D->spec_end(); + for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + FunctionDecl* FD = *it; + switch (FD->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(FD)); + break; + + // No need to visit explicit instantiations, we'll find the node + // eventually. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + break; + + case TSK_Undeclared: // Declaration of the template definition. + case TSK_ExplicitSpecialization: + break; + default: + assert(false && "Unknown specialization kind."); + } + } + + return true; +} + DEF_TRAVERSE_DECL(FunctionTemplateDecl, { TRY_TO(TraverseDecl(D->getTemplatedDecl())); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // By default, we do not traverse the instantiations of + // function templates since they do not apprear in the user code. The + // following code optionally traverses them. + if (getDerived().shouldVisitTemplateInstantiations()) { + // Explicit function specializations will be traversed from the + // context of their declaration. There is therefore no need to + // traverse them for here. + // + // In addition, we only traverse the function instantiations when + // the function template is a function template definition. + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseFunctionInstantiations(D)); + } + } }) DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { @@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { // D is the "T" in something like "template<typename T> class vector;" - if (D->hasDefaultArgument()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + if (D->hasDefaultArgument()) + TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); }) DEF_TRAVERSE_DECL(TypedefDecl, { @@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { - TRY_TO(TraverseType(I->getType())); + TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc())); } // We don't traverse the friends or the conversions, as they are // already in decls_begin()/decls_end(). @@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { // ("template set<int>;"), we do need a callback, since this // is the only callback that's made for this instantiation. // We use getTypeAsWritten() to distinguish. - // FIXME: see how we want to handle template specializations. if (TypeSourceInfo *TSI = D->getTypeAsWritten()) TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - return true; + + if (!getDerived().shouldVisitTemplateInstantiations() && + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + // Returning from here skips traversing the + // declaration context of the ClassTemplateSpecializationDecl + // (embedded in the DEF_TRAVERSE_DECL() macro) + // which contains the instantiated members of the class. + return true; }) template <typename Derived> @@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { // though that's our parent class -- we already visit all the // template args here. TRY_TO(TraverseCXXRecordHelper(D)); + + // If we're visiting instantiations, visit the instantiations of + // this template now. + if (getDerived().shouldVisitTemplateInstantiations() && + D->isThisDeclarationADefinition()) + TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D)); }) DEF_TRAVERSE_DECL(EnumConstantDecl, { @@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } TRY_TO(TraverseType(D->getResultType())); - TRY_TO(TraverseDeclContextHelper(D)); // Parameters. + + // If we're an explicit template specialization, iterate over the + // template args that were explicitly specified. + if (const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) { + if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && + FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + // A specialization might not have explicit template arguments if it has + // a templated return type and concrete arguments. + if (const TemplateArgumentListInfo *TALI = + FTSI->TemplateArgumentsAsWritten) { + TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(), + TALI->size())); + } + } + } + + for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + + if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) { + if (D->isThisDeclarationADefinition()) { + // This would be visited if we called TraverseType(D->getType()) + // above, but we don't (at least, not in the + // declaration-is-a-definition case), in order to avoid duplicate + // visiting for parameters. (We need to check parameters here, + // rather than letting D->getType() do it, so we visit default + // parameter values). So we need to re-do some of the work the + // type would do. + for (FunctionProtoType::exception_iterator + E = FuncProto->exception_begin(), + EEnd = FuncProto->exception_end(); + E != EEnd; ++E) { + TRY_TO(TraverseType(*E)); + } + } + } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. @@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { TRY_TO(TraverseDeclaratorHelper(D)); - // FIXME: This often double-counts -- for instance, for all local - // vars, though not for global vars -- because the initializer is - // also captured when the var-decl is in a DeclStmt. TRY_TO(TraverseStmt(D->getInit())); return true; } @@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, { DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseStmt(D->getDefaultArgument())); TRY_TO(TraverseVarHelper(D)); + TRY_TO(TraverseStmt(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(ParmVarDecl, { + TRY_TO(TraverseVarHelper(D)); + if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && !D->hasUnparsedDefaultArg()) @@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { !D->hasUninstantiatedDefaultArg() && !D->hasUnparsedDefaultArg()) TRY_TO(TraverseStmt(D->getDefaultArg())); - - TRY_TO(TraverseVarHelper(D)); }) #undef DEF_TRAVERSE_DECL @@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, { }) DEF_TRAVERSE_STMT(CXXCatchStmt, { - // We don't traverse S->getCaughtType(), as we are already - // traversing the exception object, which has this type. + TRY_TO(TraverseDecl(S->getExceptionDecl())); // child_begin()/end() iterates over the handler block. }) -DEF_TRAVERSE_STMT(ForStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over init, cond, inc, and body stmts. - }) - -DEF_TRAVERSE_STMT(IfStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over cond, then, and else stmts. +DEF_TRAVERSE_STMT(DeclStmt, { + for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + // Suppress the default iteration over child_begin/end by + // returning. Here's why: A DeclStmt looks like 'type var [= + // initializer]'. The decls above already traverse over the + // initializers, so we don't have to do it again (which + // child_begin/end would do). + return true; }) -DEF_TRAVERSE_STMT(WhileStmt, { - TRY_TO(TraverseDecl(S->getConditionVariable())); - // child_begin()/end() iterates over cond, then, and else stmts. - }) // These non-expr stmts (most of them), do not need any action except // iterating over the children. DEF_TRAVERSE_STMT(BreakStmt, { }) +DEF_TRAVERSE_STMT(CXXTryStmt, { }) +DEF_TRAVERSE_STMT(CaseStmt, { }) DEF_TRAVERSE_STMT(CompoundStmt, { }) DEF_TRAVERSE_STMT(ContinueStmt, { }) -DEF_TRAVERSE_STMT(CXXTryStmt, { }) -DEF_TRAVERSE_STMT(DeclStmt, { }) +DEF_TRAVERSE_STMT(DefaultStmt, { }) DEF_TRAVERSE_STMT(DoStmt, { }) +DEF_TRAVERSE_STMT(ForStmt, { }) DEF_TRAVERSE_STMT(GotoStmt, { }) +DEF_TRAVERSE_STMT(IfStmt, { }) DEF_TRAVERSE_STMT(IndirectGotoStmt, { }) DEF_TRAVERSE_STMT(LabelStmt, { }) DEF_TRAVERSE_STMT(NullStmt, { }) @@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) -DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(SwitchCase, { }) -DEF_TRAVERSE_STMT(CaseStmt, { }) -DEF_TRAVERSE_STMT(DefaultStmt, { }) +DEF_TRAVERSE_STMT(SwitchStmt, { }) +DEF_TRAVERSE_STMT(WhileStmt, { }) + DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { if (S->hasExplicitTemplateArgs()) { @@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, { TRY_TO(TraverseType(S->getAllocatedType())); }) +DEF_TRAVERSE_STMT(OffsetOfExpr, { + // The child-iterator will pick up the expression representing + // the field. + // FIMXE: for code like offsetof(Foo, a.b.c), should we get + // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isArgumentType()) + TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(CXXTypeidExpr, { + // The child-iterator will pick up the arg if it's an expression, + // but not if it's a type. + if (S->isTypeOperand()) + TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(TypesCompatibleExpr, { + TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { + TRY_TO(TraverseType(S->getQueriedType())); + }) + // These exprs (most of them), do not need any action except iterating // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, { }) @@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) DEF_TRAVERSE_STMT(BlockExpr, { }) DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) @@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) DEF_TRAVERSE_STMT(CXXThisExpr, { }) DEF_TRAVERSE_STMT(CXXThrowExpr, { }) -DEF_TRAVERSE_STMT(CXXTypeidExpr, { }) DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { }) DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) @@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) DEF_TRAVERSE_STMT(ObjCSuperExpr, { }) -DEF_TRAVERSE_STMT(OffsetOfExpr, { }) DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) -DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) -DEF_TRAVERSE_STMT(TypesCompatibleExpr, { }) -DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) -DEF_TRAVERSE_STMT(VAArgExpr, { }) +DEF_TRAVERSE_STMT(VAArgExpr, { + // The child-iterator will pick up the expression argument. + TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); + }) DEF_TRAVERSE_STMT(CXXConstructExpr, { }) DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 55e1f84..ba77829 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -177,6 +177,9 @@ public: static_cast<const decl_type*>(this))); } redecl_iterator redecls_end() const { return redecl_iterator(); } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index a0c95b1..62a6b64 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -151,22 +151,11 @@ public: struct EmptyShell { }; protected: - /// DestroyChildren - Invoked by destructors of subclasses of Stmt to - /// recursively release child AST nodes. - void DestroyChildren(ASTContext& Ctx); - /// \brief Construct an empty statement. explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); } - /// \brief Virtual method that performs the actual destruction of - /// this statement. - /// - /// Subclasses should override this method (not Destroy()) to - /// provide class-specific destruction. - virtual void DoDestroy(ASTContext &Ctx); - public: Stmt(StmtClass SC) : sClass(SC), RefCount(1) { if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); @@ -181,13 +170,6 @@ public: } #endif - /// \brief Destroy the current statement and its children. - void Destroy(ASTContext &Ctx) { - assert(RefCount >= 1); - if (--RefCount == 0) - DoDestroy(Ctx); - } - /// \brief Increases the reference count for this statement. /// /// Invoke the Retain() operation when this statement or expression @@ -221,6 +203,7 @@ public: /// This is useful in a debugger. void dump() const; void dump(SourceManager &SM) const; + void dump(llvm::raw_ostream &OS, SourceManager &SM) const; /// dumpAll - This does a dump of the specified AST fragment and all subtrees. void dumpAll() const; @@ -295,9 +278,6 @@ class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; -protected: - virtual void DoDestroy(ASTContext &Ctx); - public: DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), @@ -671,9 +651,6 @@ public: // over the initialization expression referenced by the condition variable. virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// SwitchStmt - This represents a 'switch' stmt. @@ -685,9 +662,6 @@ class SwitchStmt : public Stmt { SwitchCase *FirstCase; SourceLocation SwitchLoc; -protected: - virtual void DoDestroy(ASTContext &Ctx); - public: SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); @@ -794,9 +768,6 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// DoStmt - This represents a 'do/while' stmt. @@ -910,9 +881,6 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - -protected: - virtual void DoDestroy(ASTContext &Ctx); }; /// GotoStmt - This represents a direct goto. @@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt { StringLiteral **Constraints; Stmt **Exprs; StringLiteral **Clobbers; - -protected: - virtual void DoDestroy(ASTContext &Ctx); public: AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 4e87c27..0508f35 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -29,14 +29,14 @@ class CXXCatchStmt : public Stmt { /// The handler block. Stmt *HandlerBlock; -protected: - virtual void DoDestroy(ASTContext& Ctx); - public: CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), HandlerBlock(handlerBlock) {} + CXXCatchStmt(EmptyShell Empty) + : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} + virtual SourceRange getSourceRange() const { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } @@ -53,6 +53,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class ASTStmtReader; }; /// CXXTryStmt - A C++ try block, including all handlers. @@ -64,38 +66,46 @@ class CXXTryStmt : public Stmt { CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + CXXTryStmt(EmptyShell Empty, unsigned numHandlers) + : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } + + Stmt const * const *getStmts() const { + return reinterpret_cast<Stmt const * const*>(this + 1); + } + Stmt **getStmts() { + return reinterpret_cast<Stmt **>(this + 1); + } + public: static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, + unsigned numHandlers); + virtual SourceRange getSourceRange() const { return SourceRange(getTryLoc(), getEndLoc()); } SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getEndLoc() const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return Stmts[NumHandlers]->getLocEnd(); + return getStmts()[NumHandlers]->getLocEnd(); } CompoundStmt *getTryBlock() { - Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); - return llvm::cast<CompoundStmt>(Stmts[0]); + return llvm::cast<CompoundStmt>(getStmts()[0]); } const CompoundStmt *getTryBlock() const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return llvm::cast<CompoundStmt>(Stmts[0]); + return llvm::cast<CompoundStmt>(getStmts()[0]); } unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { - Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); - return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { - Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); - return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); } static bool classof(const Stmt *T) { @@ -105,6 +115,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class ASTStmtReader; }; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 8078451..b8c141d 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -37,68 +37,57 @@ public: if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { default: assert(0 && "Unknown binary operator!"); - case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); - case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); - case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); - case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); - case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); - case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); - case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); - case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); - case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); - - case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator); - case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator); - case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator); - case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator); - case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator); - case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator); - - case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); - case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); - case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); - case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator); - case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator); - case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); - case BinaryOperator::MulAssign: - DISPATCH(BinMulAssign, CompoundAssignOperator); - case BinaryOperator::DivAssign: - DISPATCH(BinDivAssign, CompoundAssignOperator); - case BinaryOperator::RemAssign: - DISPATCH(BinRemAssign, CompoundAssignOperator); - case BinaryOperator::AddAssign: - DISPATCH(BinAddAssign, CompoundAssignOperator); - case BinaryOperator::SubAssign: - DISPATCH(BinSubAssign, CompoundAssignOperator); - case BinaryOperator::ShlAssign: - DISPATCH(BinShlAssign, CompoundAssignOperator); - case BinaryOperator::ShrAssign: - DISPATCH(BinShrAssign, CompoundAssignOperator); - case BinaryOperator::AndAssign: - DISPATCH(BinAndAssign, CompoundAssignOperator); - case BinaryOperator::OrAssign: - DISPATCH(BinOrAssign, CompoundAssignOperator); - case BinaryOperator::XorAssign: - DISPATCH(BinXorAssign, CompoundAssignOperator); - case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator); + case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); + case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); + case BO_Mul: DISPATCH(BinMul, BinaryOperator); + case BO_Div: DISPATCH(BinDiv, BinaryOperator); + case BO_Rem: DISPATCH(BinRem, BinaryOperator); + case BO_Add: DISPATCH(BinAdd, BinaryOperator); + case BO_Sub: DISPATCH(BinSub, BinaryOperator); + case BO_Shl: DISPATCH(BinShl, BinaryOperator); + case BO_Shr: DISPATCH(BinShr, BinaryOperator); + + case BO_LT: DISPATCH(BinLT, BinaryOperator); + case BO_GT: DISPATCH(BinGT, BinaryOperator); + case BO_LE: DISPATCH(BinLE, BinaryOperator); + case BO_GE: DISPATCH(BinGE, BinaryOperator); + case BO_EQ: DISPATCH(BinEQ, BinaryOperator); + case BO_NE: DISPATCH(BinNE, BinaryOperator); + + case BO_And: DISPATCH(BinAnd, BinaryOperator); + case BO_Xor: DISPATCH(BinXor, BinaryOperator); + case BO_Or : DISPATCH(BinOr, BinaryOperator); + case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator); + case BO_LOr : DISPATCH(BinLOr, BinaryOperator); + case BO_Assign: DISPATCH(BinAssign, BinaryOperator); + case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator); + case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator); + case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator); + case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator); + case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator); + case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator); + case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator); + case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator); + case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator); + case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator); + case BO_Comma: DISPATCH(BinComma, BinaryOperator); } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { default: assert(0 && "Unknown unary operator!"); - case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator); - case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator); - case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator); - case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator); - case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); - case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator); - case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator); - case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator); - case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator); - case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator); - case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator); - case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator); - case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator); - case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator); + case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator); + case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator); + case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator); + case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator); + case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); + case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator); + case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator); + case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator); + case UO_Not: DISPATCH(UnaryNot, UnaryOperator); + case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator); + case UO_Real: DISPATCH(UnaryReal, UnaryOperator); + case UO_Imag: DISPATCH(UnaryImag, UnaryOperator); + case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator); } } @@ -163,7 +152,7 @@ public: UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) - UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) + UNARYOP_FALLBACK(Extension) #undef UNARYOP_FALLBACK // Base case, ignore it. :) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 4c148e8..92e62a5 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -289,7 +289,18 @@ public: L += R; return L; } + + Qualifiers &operator-=(Qualifiers R) { + Mask = Mask & ~(R.Mask); + return *this; + } + /// \brief Compute the difference between two qualifier sets. + friend Qualifiers operator-(Qualifiers L, Qualifiers R) { + L -= R; + return L; + } + std::string getAsString() const; std::string getAsString(const PrintingPolicy &Policy) const { std::string Buffer; @@ -399,7 +410,8 @@ enum CallingConv { CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall // __attribute__((thiscall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86Pascal // __attribute__((pascal)) }; @@ -787,12 +799,12 @@ private: /// \brief Linkage of this type. mutable unsigned CachedLinkage : 2; - /// \brief FromPCH - Whether this type comes from a PCH file. - mutable bool FromPCH : 1; + /// \brief FromAST - Whether this type comes from an AST file. + mutable bool FromAST : 1; - /// \brief Set whether this type comes from a PCH file. - void setFromPCH(bool V = true) const { - FromPCH = V; + /// \brief Set whether this type comes from an AST file. + void setFromAST(bool V = true) const { + FromAST = V; } protected: @@ -806,16 +818,15 @@ protected: Type(TypeClass tc, QualType Canonical, bool dependent) : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), TC(tc), Dependent(dependent), LinkageKnown(false), - CachedLinkage(NoLinkage), FromPCH(false) {} - virtual ~Type() {} - virtual void Destroy(ASTContext& C); + CachedLinkage(NoLinkage), FromAST(false) {} + virtual ~Type(); friend class ASTContext; public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } - /// \brief Whether this type comes from a PCH file. - bool isFromPCH() const { return FromPCH; } + /// \brief Whether this type comes from an AST file. + bool isFromAST() const { return FromAST; } bool isCanonicalUnqualified() const { return CanonicalType.getTypePtr() == this; @@ -824,14 +835,6 @@ public: /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. - /// \brief Determines whether the type describes an object in memory. - /// - /// Note that this definition of object type corresponds to the C++ - /// definition of object type, which includes incomplete types, as - /// opposed to the C definition (which does not include incomplete - /// types). - bool isObjectType() const; - /// isIncompleteType - Return true if this is an incomplete type. /// A type that can describe objects, but which lacks information needed to /// determine its size (e.g. void, or a fwd declared struct). Clients of this @@ -906,6 +909,7 @@ public: bool isFunctionPointerType() const; bool isMemberPointerType() const; bool isMemberFunctionPointerType() const; + bool isMemberDataPointerType() const; bool isArrayType() const; bool isConstantArrayType() const; bool isIncompleteArrayType() const; @@ -926,6 +930,7 @@ public: bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedClassType() const; // Class<foo> + bool isObjCObjectOrInterfaceType() const; bool isObjCIdType() const; // id bool isObjCClassType() const; // Class bool isObjCSelType() const; // Class @@ -952,10 +957,22 @@ public: /// an objective pointer type for the purpose of GC'ability bool hasObjCPointerRepresentation() const; + /// \brief Determine whether this type has an integer representation + /// of some sort, e.g., it is an integer type or a vector. + bool hasIntegerRepresentation() const; + + /// \brief Determine whether this type has an signed integer representation + /// of some sort, e.g., it is an signed integer type or a vector. + bool hasSignedIntegerRepresentation() const; + + /// \brief Determine whether this type has an unsigned integer representation + /// of some sort, e.g., it is an unsigned integer type or a vector. + bool hasUnsignedIntegerRepresentation() const; + /// \brief Determine whether this type has a floating-point representation /// of some sort, e.g., it is a floating-point type or a vector thereof. bool hasFloatingRepresentation() const; - + // Type Checking Functions: Check to see if this type is structurally the // specified type, ignoring typedefs and qualifiers, and return a pointer to // the best type we can. @@ -975,7 +992,8 @@ public: /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; - // Member-template getAs<specific type>'. This scheme will eventually + // Member-template getAs<specific type>'. Look through sugar for + // an instance of <specific type>. This scheme will eventually // replace the specific getAsXXXX methods above. // // There are some specializations of this member template listed @@ -1035,8 +1053,8 @@ public: void dump() const; static bool classof(const Type *) { return true; } - friend class PCHReader; - friend class PCHWriter; + friend class ASTReader; + friend class ASTWriter; }; template <> inline const TypedefType *Type::getAs() const { @@ -1353,9 +1371,20 @@ protected: virtual Linkage getLinkageImpl() const; public: - QualType getPointeeType() const { return PointeeType; } + /// Returns true if the member type (i.e. the pointee type) is a + /// function type rather than a data-member type. + bool isMemberFunctionPointer() const { + return PointeeType->isFunctionProtoType(); + } + + /// Returns true if the member type (i.e. the pointee type) is a + /// data type rather than a function type. + bool isMemberDataPointer() const { + return !PointeeType->isFunctionProtoType(); + } + const Type *getClass() const { return Class; } bool isSugared() const { return false; } @@ -1454,6 +1483,17 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + + /// \brief Determine the number of bits required to address a member of + // an array with the given element type and number of elements. + static unsigned getNumAddressingBits(ASTContext &Context, + QualType ElementType, + const llvm::APInt &NumElements); + + /// \brief Determine the maximum number of active bits that an array's size + /// can require, which limits the maximum size of the array. + static unsigned getMaxSizeBits(ASTContext &Context); + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSize(), getSizeModifier(), getIndexTypeCVRQualifiers()); @@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType { : ArrayType(VariableArray, et, can, sm, tq), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { @@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType { : ArrayType(DependentSizedArray, et, can, sm, tq), Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { @@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {} friend class ASTContext; - virtual void Destroy(ASTContext& C); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -1844,13 +1881,13 @@ class FunctionType : public Type { // * FunctionNoProtoType::Profile // * FunctionProtoType::Profile // * TypePrinter::PrintFunctionProto - // * PCH read and write + // * AST read and write // * Codegen class ExtInfo { public: // Constructor with no defaults. Use this when you know that you - // have all the elements (when reading a PCH file for example). + // have all the elements (when reading an AST file for example). ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : NoReturn(noReturn), RegParm(regParm), CC(cc) {} @@ -1892,7 +1929,7 @@ class FunctionType : public Type { // The value passed to __attribute__((regparm(x))) unsigned RegParm; // The calling convention as specified via - // __attribute__((cdecl|stdcall|fastcall|thiscall)) + // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal)) CallingConv CC; }; @@ -2259,14 +2296,9 @@ public: }; class TagType : public Type { - /// Stores the TagDecl associated with this type. The decl will - /// point to the TagDecl that actually defines the entity (or is a - /// definition in progress), if there is such a definition. The - /// single-bit value will be non-zero when this tag is in the - /// process of being defined. - mutable llvm::PointerIntPair<TagDecl *, 1> decl; - friend class ASTContext; - friend class TagDecl; + /// Stores the TagDecl associated with this type. The decl may point to any + /// TagDecl that declares the entity. + TagDecl * decl; protected: TagType(TypeClass TC, const TagDecl *D, QualType can); @@ -2274,12 +2306,11 @@ protected: virtual Linkage getLinkageImpl() const; public: - TagDecl *getDecl() const { return decl.getPointer(); } + TagDecl *getDecl() const; /// @brief Determines whether this type is in the process of being /// defined. - bool isBeingDefined() const { return decl.getInt(); } - void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } + bool isBeingDefined() const; static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; @@ -2468,8 +2499,6 @@ class TemplateSpecializationType const TemplateArgument *Args, unsigned NumArgs, QualType Canon); - virtual void Destroy(ASTContext& C); - friend class ASTContext; // ASTContext creates these public: @@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type { QualType InjectedType; friend class ASTContext; // ASTContext creates these. - friend class TagDecl; // TagDecl mutilates the Decl - friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not - // currently suitable for PCH reading, too much + friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not + // currently suitable for AST reading, too much // interdependencies. InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), true), @@ -2592,7 +2620,7 @@ public: return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } - CXXRecordDecl *getDecl() const { return Decl; } + CXXRecordDecl *getDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType : const TemplateArgument *Args, QualType Canon); - virtual void Destroy(ASTContext& C); - friend class ASTContext; // ASTContext creates these public: @@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} public: - void Destroy(ASTContext& C); // key function - void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType Base, @@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType { Decl(const_cast<ObjCInterfaceDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. public: - void Destroy(ASTContext& C); // key function - /// getDecl - Get the declaration of this interface. ObjCInterfaceDecl *getDecl() const { return Decl; } @@ -3103,8 +3125,6 @@ protected: virtual Linkage getLinkageImpl() const; public: - void Destroy(ASTContext& C); - /// getPointeeType - Gets the type pointed to by this ObjC pointer. /// The result will always be an ObjCObjectType or sugar thereof. QualType getPointeeType() const { return PointeeType; } @@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const { } inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) - return T->getPointeeType()->isFunctionType(); + return T->isMemberFunctionPointer(); + else + return false; +} +inline bool Type::isMemberDataPointerType() const { + if (const MemberPointerType* T = getAs<MemberPointerType>()) + return T->isMemberDataPointer(); else return false; } @@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const { inline bool Type::isObjCObjectType() const { return isa<ObjCObjectType>(CanonicalType); } +inline bool Type::isObjCObjectOrInterfaceType() const { + return isa<ObjCInterfaceType>(CanonicalType) || + isa<ObjCObjectType>(CanonicalType); +} + inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedIdType(); diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 842c068..f1c64bd 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -341,6 +341,10 @@ private: template <class Base, class Derived, class TypeClass> class InheritingConcreteTypeLoc : public Base { public: + static bool classofType(const Type *Ty) { + return TypeClass::classof(Ty); + } + static bool classof(const TypeLoc *TL) { return Derived::classofType(TL->getTypePtr()); } diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 1a050d2..7cf0d5e 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -17,6 +17,7 @@ #define LLVM_CLANG_TYPE_ORDERING_H #include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" #include <functional> namespace clang { @@ -51,6 +52,26 @@ namespace llvm { return LHS == RHS; } }; + + template<> struct DenseMapInfo<clang::CanQualType> { + static inline clang::CanQualType getEmptyKey() { + return clang::CanQualType(); + } + + static inline clang::CanQualType getTombstoneKey() { + using clang::CanQualType; + return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); + } + + static unsigned getHashValue(clang::CanQualType Val) { + return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ + ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); + } + + static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) { + return LHS == RHS; + } + }; } #endif |