diff options
author | dim <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
commit | 110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab (patch) | |
tree | 64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /include/clang/AST | |
parent | a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff) | |
download | FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.zip FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.tar.gz |
Vendor import of clang trunk r130700:
http://llvm.org/svn/llvm-project/cfe/trunk@130700
Diffstat (limited to 'include/clang/AST')
28 files changed, 2448 insertions, 786 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 08ee4ef..fcc9176 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -89,7 +89,7 @@ public: /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to - /// a GetASTMutationListener here. + /// an ASTMutationListener here. virtual ASTMutationListener *GetASTMutationListener() { return 0; } /// \brief If the consumer is interested in entities being deserialized from diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c0eeb5a..28ec8cf 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -14,10 +14,12 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/VersionTuple.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -27,6 +29,7 @@ #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" @@ -68,7 +71,7 @@ namespace clang { class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; - class TypedefDecl; + class TypedefNameDecl; class UsingDecl; class UsingShadowDecl; class UnresolvedSetIterator; @@ -77,7 +80,7 @@ namespace clang { /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. -class ASTContext { +class ASTContext : public llvm::RefCountedBase<ASTContext> { ASTContext &this_() { return *this; } mutable std::vector<Type*> Types; @@ -96,7 +99,8 @@ class ASTContext { DependentSizedExtVectorTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; - mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> + FunctionProtoTypes; mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; @@ -310,6 +314,9 @@ class ASTContext { llvm::OwningPtr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); + /// \brief The logical -> physical address space map. + const LangAS::Map &AddrSpaceMap; + friend class ASTDeclReader; public: @@ -335,6 +342,14 @@ public: } void Deallocate(void *Ptr) const { } + /// Return the total amount of physical memory allocated for representing + /// AST nodes and type information. + size_t getASTAllocatedMemory() const { + return BumpAlloc.getTotalMemory(); + } + /// Return the total memory used for various side tables. + size_t getSideTableAllocatedMemory() const; + PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; } @@ -381,6 +396,16 @@ public: FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + + /// ZeroBitfieldFollowsNonBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the non-bitfield 'LastFD'. + bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; + + /// ZeroBitfieldFollowsBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the bitfield 'LastFD'. + bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; // Access to the set of methods overridden by the given C++ method. typedef CXXMethodVector::iterator overridden_cxx_method_iterator; @@ -413,10 +438,13 @@ public: CanQualType FloatTy, DoubleTy, LongDoubleTy; CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; - CanQualType OverloadTy; - CanQualType DependentTy; + CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; + // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. + mutable QualType AutoDeductTy; // Deduction against 'auto'. + mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, @@ -654,9 +682,9 @@ public: } /// getTypedefType - Return the unique reference to the type for the - /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()) - const; + /// specified typedef-name decl. + QualType getTypedefType(const TypedefNameDecl *Decl, + QualType Canon = QualType()) const; QualType getRecordType(const RecordDecl *Decl) const; @@ -676,7 +704,7 @@ public: QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name = 0) const; + TemplateTypeParmDecl *ParmDecl = 0) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, @@ -739,6 +767,12 @@ public: /// getAutoType - C++0x deduced auto type. QualType getAutoType(QualType DeducedType) const; + /// getAutoDeductType - C++0x deduction pattern for 'auto' type. + QualType getAutoDeductType() const; + + /// getAutoRRefDeductType - C++0x deduction pattern for 'auto &&' type. + QualType getAutoRRefDeductType() const; + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; @@ -1294,6 +1328,21 @@ public: QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, QualType typeDomain) const; + unsigned getTargetAddressSpace(QualType T) const { + return getTargetAddressSpace(T.getQualifiers()); + } + + unsigned getTargetAddressSpace(Qualifiers Q) const { + return getTargetAddressSpace(Q.getAddressSpace()); + } + + unsigned getTargetAddressSpace(unsigned AS) const { + if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) + return AS; + else + return AddrSpaceMap[AS - LangAS::Offset]; + } + private: // Helper for integer ordering unsigned getIntegerRank(const Type *T) const; @@ -1332,7 +1381,8 @@ public: const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT); + const ObjCObjectPointerType *RHSOPT, + bool BlockReturnType); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1340,7 +1390,7 @@ public: // Functions for calculating composite types QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false); + bool Unqualified = false, bool BlockReturnType = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); QualType mergeFunctionArgumentTypes(QualType, QualType, @@ -1528,13 +1578,13 @@ private: }; /// @brief Utility function for constructing a nullary selector. -static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetNullarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(0, &II); } /// @brief Utility function for constructing an unary selector. -static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetUnarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); } diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 1ab53b3..1cb803a 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 01e6180..470cca8 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -20,6 +20,8 @@ namespace clang { class CXXRecordDecl; class ClassTemplateDecl; class ClassTemplateSpecializationDecl; + class FunctionDecl; + class FunctionTemplateDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -41,6 +43,17 @@ public: /// template declaration. virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {} + + /// \brief A template specialization (or partial one) was added to the + /// template declaration. + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) {} + + /// \brief An implicit member got a definition. + virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} + + /// \brief A static data member was implicitly instantiated. + virtual void StaticDataMemberInstantiated(const VarDecl *D) {} }; } // end namespace clang diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 67968fd..7190239 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -17,9 +17,11 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "clang/Basic/AttrKinds.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include <cassert> #include <cstring> #include <algorithm> @@ -120,6 +122,19 @@ public: static bool classof(const InheritableAttr *) { return true; } }; +class InheritableParamAttr : public InheritableAttr { +protected: + InheritableParamAttr(attr::Kind AK, SourceLocation L) + : InheritableAttr(AK, L) {} + +public: + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() <= attr::LAST_INHERITABLE_PARAM; + } + static bool classof(const InheritableParamAttr *) { return true; } +}; + #include "clang/AST/Attrs.inc" /// AttrVec - A vector of Attr, which is how they are stored on the AST. diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 2d30cb3..d712e7d 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -87,7 +87,7 @@ public: /// BasePaths - Represents the set of paths from a derived class to /// one of its (direct or indirect) bases. For example, given the -/// following class hierachy: +/// following class hierarchy: /// /// @code /// class A { }; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 4d7fcfd..b3550f8 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -655,7 +655,8 @@ struct CanProxyAdaptor<TemplateTypeParmType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) }; template<> diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index cf909e8..d7cbd08 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -34,7 +34,7 @@ namespace clang { /// architectures where the two are the same size. /// /// For portability, never assume that a target character is 8 bits wide. Use - /// CharUnit values whereever you calculate sizes, offsets, or alignments + /// CharUnit values wherever you calculate sizes, offsets, or alignments /// in character units. class CharUnits { public: @@ -70,10 +70,24 @@ namespace clang { Quantity += Other.Quantity; return *this; } + CharUnits& operator++ () { + ++Quantity; + return *this; + } + CharUnits operator++ (int) { + return CharUnits(Quantity++); + } CharUnits& operator-= (const CharUnits &Other) { Quantity -= Other.Quantity; return *this; } + CharUnits& operator-- () { + --Quantity; + return *this; + } + CharUnits operator-- (int) { + return CharUnits(Quantity--); + } // Comparison operators. bool operator== (const CharUnits &Other) const { diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 31cee24..ef49205 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/Linkage.h" +#include "llvm/ADT/Optional.h" namespace clang { class CXXTemporary; @@ -119,14 +120,6 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } - llvm::StringRef getMessageUnavailableAttr(bool unavailable) const { - if (!unavailable) - return ""; - if (const UnavailableAttr *UA = getAttr<UnavailableAttr>()) - return UA->getMessage(); - return ""; - } - /// 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 @@ -281,6 +274,10 @@ public: /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; + /// \brief If visibility was explicitly specified for this + /// declaration, return that visibility. + llvm::Optional<Visibility> getExplicitVisibility() const; + /// \brief Clear the linkage cache in response to a change /// to the declaration. void ClearLinkageCache(); @@ -310,16 +307,32 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// location is where the __label__ is. class LabelDecl : public NamedDecl { LabelStmt *TheStmt; - LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S) - : NamedDecl(Label, DC, L, II), TheStmt(S) {} - + /// LocStart - For normal labels, this is the same as the main declaration + /// label, i.e., the location of the identifier; for GNU local labels, + /// this is the location of the __label__ keyword. + SourceLocation LocStart; + + LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, + LabelStmt *S, SourceLocation StartL) + : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *II); + SourceLocation IdentL, IdentifierInfo *II); + static LabelDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II, + SourceLocation GnuLabelL); LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } - + + bool isGnuLocal() const { return LocStart != getLocation(); } + void setLocStart(SourceLocation L) { LocStart = L; } + + SourceRange getSourceRange() const { + return SourceRange(LocStart, getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LabelDecl *D) { return true; } @@ -330,7 +343,11 @@ public: class NamespaceDecl : public NamedDecl, public DeclContext { bool IsInline : 1; - SourceLocation LBracLoc, RBracLoc; + /// LocStart - The starting location of the source range, pointing + /// to either the namespace or the inline keyword. + SourceLocation LocStart; + /// RBraceLoc - The ending location of the source range. + SourceLocation RBraceLoc; // For extended namespace definitions: // @@ -357,13 +374,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext { /// namespace declaration (which the boolean indicates). llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace; - NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { } + NamespaceDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + IsInline(false), LocStart(StartLoc), RBraceLoc(), + NextNamespace(), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id); /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -427,7 +447,7 @@ public: void setAnonymousNamespace(NamespaceDecl *D) { assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent() == this); + assert(!D || D->getParent()->getRedeclContext() == this); getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } @@ -437,14 +457,14 @@ public: } virtual SourceRange getSourceRange() const { - return SourceRange(getLocation(), RBracLoc); + return SourceRange(LocStart, RBraceLoc); } - SourceLocation getLBracLoc() const { return LBracLoc; } - SourceLocation getRBracLoc() const { return RBracLoc; } - void setLBracLoc(SourceLocation L) { LBracLoc = L; } - void setRBracLoc(SourceLocation R) { RBracLoc = R; } - + SourceLocation getLocStart() const { return LocStart; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setLocStart(SourceLocation L) { LocStart = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceDecl *D) { return true; } @@ -484,16 +504,24 @@ public: /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { NestedNameSpecifierLoc QualifierLoc; - /// NumTemplParamLists - The number of template parameter lists - /// that were matched against the template-ids occurring into the NNS. + + /// NumTemplParamLists - The number of "outer" template parameter lists. + /// The count includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". unsigned NumTemplParamLists; + /// TemplParamLists - A new-allocated array of size NumTemplParamLists, - /// containing pointers to the matched template parameter lists. + /// containing pointers to the "outer" template parameter lists. + /// It includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". TemplateParameterList** TemplParamLists; /// Default constructor. QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} - /// setTemplateParameterListsInfo - Sets info about matched template + + /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, @@ -516,14 +544,20 @@ class DeclaratorDecl : public ValueDecl { llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; + /// InnerLocStart - The start of the source range for this declaration, + /// ignoring outer template declarations. + SourceLocation InnerLocStart; + bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); } protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo) - : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + SourceLocation StartL) + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) { + } public: TypeSourceInfo *getTypeSourceInfo() const { @@ -540,14 +574,14 @@ public: /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return getLocation(); } + SourceLocation getInnerLocStart() const { return InnerLocStart; } + void setInnerLocStart(SourceLocation L) { InnerLocStart = L; } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), getLocation()); - } + + virtual SourceRange getSourceRange() const; /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -574,9 +608,7 @@ public: return getExtInfo()->TemplParamLists[index]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); SourceLocation getTypeSpecStartLoc() const; @@ -650,32 +682,77 @@ protected: mutable InitType Init; private: - // FIXME: This can be packed into the bitfields in Decl. - unsigned SClass : 3; - unsigned SClassAsWritten : 3; - bool ThreadSpecified : 1; - bool HasCXXDirectInit : 1; - - /// \brief Whether this variable is the exception variable in a C++ catch - /// or an Objective-C @catch statement. - bool ExceptionVar : 1; + class VarDeclBitfields { + friend class VarDecl; + friend class ASTDeclReader; + + unsigned SClass : 3; + unsigned SClassAsWritten : 3; + unsigned ThreadSpecified : 1; + unsigned HasCXXDirectInit : 1; + + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + unsigned ExceptionVar : 1; - /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization (NRVO). - bool NRVOVariable : 1; + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization (NRVO). + unsigned NRVOVariable : 1; + + /// \brief Whether this variable is the for-range-declaration in a C++0x + /// for-range statement. + unsigned CXXForRangeDecl : 1; + }; + enum { NumVarDeclBits = 13 }; // two reserved bits for now - friend class StmtIteratorBase; friend class ASTDeclReader; + friend class StmtIteratorBase; protected: - VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + class ParmVarDeclBitfields { + friend class ParmVarDecl; + friend class ASTDeclReader; + + unsigned : NumVarDeclBits; + + /// Whether this parameter inherits a default argument from a + /// prior declaration. + unsigned HasInheritedDefaultArg : 1; + + /// Whether this parameter undergoes K&R argument promotion. + unsigned IsKNRPromoted : 1; + + /// Whether this parameter is an ObjC method parameter or not. + unsigned IsObjCMethodParam : 1; + + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. + /// Otherwise, the number of function parameter scopes enclosing + /// the function parameter scope in which this parameter was + /// declared. + unsigned ScopeDepthOrObjCQuals : 8; + + /// The number of parameters preceding this parameter in the + /// function parameter scope in which it was declared. + unsigned ParameterIndex : 8; + }; + + union { + unsigned AllBits; + VarDeclBitfields VarDeclBits; + ParmVarDeclBitfields ParmVarDeclBits; + }; + + VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), - ThreadSpecified(false), HasCXXDirectInit(false), - ExceptionVar(false), NRVOVariable(false) { - SClass = SC; - SClassAsWritten = SCAsWritten; + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { + assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); + assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); + AllBits = 0; + VarDeclBits.SClass = SC; + VarDeclBits.SClassAsWritten = SCAsWritten; + // Everything else is implicitly initialized to false. } typedef Redeclarable<VarDecl> redeclarable_base; @@ -691,26 +768,27 @@ public: } static VarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass S, - StorageClass SCAsWritten); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten); - virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; - StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClass() const { + return (StorageClass) VarDeclBits.SClass; + } StorageClass getStorageClassAsWritten() const { - return (StorageClass) SClassAsWritten; + return (StorageClass) VarDeclBits.SClassAsWritten; } void setStorageClass(StorageClass SC); void setStorageClassAsWritten(StorageClass SC) { assert(isLegalForVariable(SC)); - SClassAsWritten = SC; + VarDeclBits.SClassAsWritten = SC; } - void setThreadSpecified(bool T) { ThreadSpecified = T; } + void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } bool isThreadSpecified() const { - return ThreadSpecified; + return VarDeclBits.ThreadSpecified; } /// hasLocalStorage - Returns true if a variable with function scope @@ -988,7 +1066,7 @@ public: Eval->IsICE = IsICE; } - void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } + void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; } /// hasCXXDirectInitializer - If true, the initializer was a direct /// initializer, e.g: "int x(1);". The Init expression will be the expression @@ -997,15 +1075,15 @@ public: /// by checking hasCXXDirectInitializer. /// bool hasCXXDirectInitializer() const { - return HasCXXDirectInit; + return VarDeclBits.HasCXXDirectInit; } /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C @catch statement. bool isExceptionVariable() const { - return ExceptionVar; + return VarDeclBits.ExceptionVar; } - void setExceptionVariable(bool EV) { ExceptionVar = EV; } + void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). @@ -1017,8 +1095,13 @@ public: /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. - bool isNRVOVariable() const { return NRVOVariable; } - void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + bool isNRVOVariable() const { return VarDeclBits.NRVOVariable; } + void setNRVOVariable(bool NRVO) { VarDeclBits.NRVOVariable = NRVO; } + + /// \brief Determine whether this variable is the for-range-declaration in + /// a C++0x for-range statement. + bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; } + void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; } /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -1048,12 +1131,12 @@ public: class ImplicitParamDecl : public VarDecl { public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T); - ImplicitParamDecl(DeclContext *DC, SourceLocation loc, - IdentifierInfo *name, QualType type) - : VarDecl(ImplicitParam, DC, loc, name, type, + ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, + IdentifierInfo *Id, QualType Type) + : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, /*tinfo*/ 0, SC_None, SC_None) { setImplicit(); } @@ -1064,35 +1147,85 @@ public: static bool classofKind(Kind K) { return K == ImplicitParam; } }; -/// ParmVarDecl - Represent a parameter to a function. +/// ParmVarDecl - Represents a parameter to a function. class ParmVarDecl : public VarDecl { - // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum - /// FIXME: Also can be paced into the bitfields in Decl. - /// in, inout, etc. - unsigned objcDeclQualifier : 6; - bool HasInheritedDefaultArg : 1; +public: + enum { MaxFunctionScopeDepth = 255 }; + enum { MaxFunctionScopeIndex = 255 }; protected: - ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), - objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { + assert(ParmVarDeclBits.HasInheritedDefaultArg == false); + assert(ParmVarDeclBits.IsKNRPromoted == false); + assert(ParmVarDeclBits.IsObjCMethodParam == false); setDefaultArg(DefArg); } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg); + void setObjCMethodScopeInfo(unsigned parameterIndex) { + ParmVarDeclBits.IsObjCMethodParam = true; + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) { + assert(!ParmVarDeclBits.IsObjCMethodParam); + + ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; + assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!"); + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + bool isObjCMethodParameter() const { + return ParmVarDeclBits.IsObjCMethodParam; + } + + unsigned getFunctionScopeDepth() const { + if (ParmVarDeclBits.IsObjCMethodParam) return 0; + return ParmVarDeclBits.ScopeDepthOrObjCQuals; + } + + /// Returns the index of this parameter in its prototype or method scope. + unsigned getFunctionScopeIndex() const { + return ParmVarDeclBits.ParameterIndex; + } + ObjCDeclQualifier getObjCDeclQualifier() const { - return ObjCDeclQualifier(objcDeclQualifier); + if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None; + return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals); } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { - objcDeclQualifier = QTVal; + assert(ParmVarDeclBits.IsObjCMethodParam); + ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal; + } + + /// True if the value passed to this parameter must undergo + /// K&R-style default argument promotion: + /// + /// C99 6.5.2.2. + /// If the expression that denotes the called function has a type + /// that does not include a prototype, the integer promotions are + /// performed on each argument, and arguments that have type float + /// are promoted to double. + bool isKNRPromoted() const { + return ParmVarDeclBits.IsKNRPromoted; + } + void setKNRPromoted(bool promoted) { + ParmVarDeclBits.IsKNRPromoted = promoted; } Expr *getDefaultArg(); @@ -1158,11 +1291,11 @@ public: } bool hasInheritedDefaultArg() const { - return HasInheritedDefaultArg; + return ParmVarDeclBits.HasInheritedDefaultArg; } void setHasInheritedDefaultArg(bool I = true) { - HasInheritedDefaultArg = I; + ParmVarDeclBits.HasInheritedDefaultArg = I; } QualType getOriginalType() const { @@ -1233,6 +1366,7 @@ private: bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; + bool IsLateTemplateParsed : 1; /// \brief End part of this FunctionDecl's source range. /// @@ -1302,17 +1436,20 @@ private: void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams); protected: - FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, + FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified) - : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, + StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()), + HasImplicitReturnZero(false), IsLateTemplateParsed(false), + EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1328,22 +1465,25 @@ public: return redeclarable_base::redecls_end(); } - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true) { - DeclarationNameInfo NameInfo(N, L); - return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, + DeclarationNameInfo NameInfo(N, NLoc); + return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, + SC, SCAsWritten, isInlineSpecified, hasWrittenPrototype); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true); @@ -1356,12 +1496,9 @@ public: const PrintingPolicy &Policy, bool Qualified) const; - virtual SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), EndRangeLoc); - } - void setLocEnd(SourceLocation E) { - EndRangeLoc = E; - } + void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } + + virtual SourceRange getSourceRange() const; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1395,7 +1532,9 @@ public: /// previous definition); for that information, use getBody. /// FIXME: Should return true if function is deleted or defaulted. However, /// CodeGenModule.cpp uses it, and I don't know if this would break it. - bool isThisDeclarationADefinition() const { return Body; } + bool isThisDeclarationADefinition() const { + return Body || IsLateTemplateParsed; + } void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } @@ -1412,6 +1551,14 @@ public: bool isPure() const { return IsPure; } void setPure(bool P = true); + /// Whether this is a constexpr function or constexpr constructor. + // FIXME: C++0x: Implement tracking of the constexpr specifier. + bool isConstExpr() const { return false; } + + /// Whether this templated function will be late parsed. + bool isLateTemplateParsed() const { return IsLateTemplateParsed; } + void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; } + /// Whether this function is "trivial" in some specialized C++ senses. /// Can only be true for default constructors, copy constructors, /// copy assignment operators, and destructors. Not meaningful until @@ -1757,16 +1904,17 @@ class FieldDecl : public DeclaratorDecl { Expr *BitWidth; protected: - FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - Expr *BW, bool Mutable) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), + FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) { } public: static FieldDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable); /// getFieldIndex - Returns the index of this field within its record, @@ -1803,7 +1951,9 @@ public: RecordDecl *getParent() { return cast<RecordDecl>(getDeclContext()); } - + + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } @@ -1895,6 +2045,8 @@ class TypeDecl : public NamedDecl { /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. mutable const Type *TypeForDecl; + /// LocStart - The start of the source range for this declaration. + SourceLocation LocStart; friend class ASTContext; friend class DeclContext; friend class TagDecl; @@ -1902,15 +2054,24 @@ class TypeDecl : public NamedDecl { friend class TagType; protected: - TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} + TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation StartL = SourceLocation()) + : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {} public: // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } + SourceLocation getLocStart() const { return LocStart; } + void setLocStart(SourceLocation L) { LocStart = L; } + virtual SourceRange getSourceRange() const { + if (LocStart.isValid()) + return SourceRange(LocStart, getLocation()); + else + return SourceRange(getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypeDecl *D) { return true; } @@ -1918,17 +2079,21 @@ public: }; -class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { +/// Base class for declarations which introduce a typedef-name. +class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; - TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - protected: - typedef Redeclarable<TypedefDecl> redeclarable_base; - virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} + + typedef Redeclarable<TypedefNameDecl> redeclarable_base; + virtual TypedefNameDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; @@ -1939,19 +2104,15 @@ public: return redeclarable_base::redecls_end(); } - static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - TypeSourceInfo *TInfo); - TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } - /// Retrieves the canonical declaration of this typedef. - TypedefDecl *getCanonicalDecl() { + /// Retrieves the canonical declaration of this typedef-name. + TypedefNameDecl *getCanonicalDecl() { return getFirstDeclaration(); } - const TypedefDecl *getCanonicalDecl() const { + const TypedefNameDecl *getCanonicalDecl() const { return getFirstDeclaration(); } @@ -1964,11 +2125,51 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypedefNameDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstTypedefName && K <= lastTypedefName; + } +}; + +/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' +/// type specifier. +class TypedefDecl : public TypedefNameDecl { + TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypedefDecl *D) { return true; } static bool classofKind(Kind K) { return K == Typedef; } }; -class TypedefDecl; +/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x +/// alias-declaration. +class TypeAliasDecl : public TypedefNameDecl { + TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TypeAlias; } +}; /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl @@ -2013,32 +2214,31 @@ protected: bool IsFixed : 1; private: - SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. typedef QualifierInfo ExtInfo; - /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name + /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of - /// a typedef, it points to the TypedefDecl (used for mangling); - /// otherwise, it is a null (TypedefDecl) pointer. - llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier; + /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); + /// otherwise, it is a null (TypedefNameDecl) pointer. + llvm::PointerUnion<TypedefNameDecl*, ExtInfo*> TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); } - ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo*>(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo*>(); } const ExtInfo *getExtInfo() const { - return TypedefDeclOrQualifier.get<ExtInfo*>(); + return TypedefNameDeclOrQualifier.get<ExtInfo*>(); } protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) - : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), - TypedefDeclOrQualifier((TypedefDecl*) 0) { + TagDecl *PrevDecl, SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), + TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; @@ -2068,12 +2268,9 @@ public: SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } - void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } - /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return TagKeywordLoc; } + SourceLocation getInnerLocStart() const { return getLocStart(); } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. @@ -2146,11 +2343,11 @@ public: bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } - TypedefDecl *getTypedefForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); + TypedefNameDecl *getTypedefNameForAnonDecl() const { + return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); } - void setTypedefForAnonDecl(TypedefDecl *TDD); + void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -2177,9 +2374,7 @@ public: return getExtInfo()->TemplParamLists[i]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2235,18 +2430,19 @@ class EnumDecl : public TagDecl { NumBitsMask = (1 << NumBitsWidth) - 1 }; - EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL, + EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { - assert(Scoped || !ScopedUsingClassTag); - IntegerType = (const Type*)0; - NumNegativeBits = 0; - NumPositiveBits = 0; - IsScoped = Scoped; - IsScopedUsingClassTag = ScopedUsingClassTag; - IsFixed = Fixed; - } + : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), + InstantiatedFrom(0) { + assert(Scoped || !ScopedUsingClassTag); + IntegerType = (const Type*)0; + NumNegativeBits = 0; + NumPositiveBits = 0; + IsScoped = Scoped; + IsScopedUsingClassTag = ScopedUsingClassTag; + IsFixed = Fixed; + } public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); @@ -2263,8 +2459,8 @@ public: } static EnumDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, EnumDecl *PrevDecl, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); @@ -2326,7 +2522,7 @@ public: return IntegerType.dyn_cast<TypeSourceInfo*>(); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// non-negative enumerators of this enum. unsigned getNumPositiveBits() const { return NumPositiveBits; @@ -2336,7 +2532,7 @@ public: assert(NumPositiveBits == Num && "can't store this bitcount"); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: /// @@ -2419,14 +2615,13 @@ class RecordDecl : public TagDecl { protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - RecordDecl *PrevDecl, SourceLocation TKL); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl *PrevDecl); public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - RecordDecl* PrevDecl = 0); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl* PrevDecl = 0); static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); const RecordDecl *getPreviousDeclaration() const { @@ -2519,11 +2714,21 @@ private: class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; - FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) - : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} + SourceLocation RParenLoc; + FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, + SourceLocation StartL, SourceLocation EndL) + : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {} public: static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, StringLiteral *Str); + StringLiteral *Str, SourceLocation AsmLoc, + SourceLocation RParenLoc); + + SourceLocation getAsmLoc() const { return getLocation(); } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + SourceRange getSourceRange() const { + return SourceRange(getAsmLoc(), getRParenLoc()); + } const StringLiteral *getAsmString() const { return AsmString; } StringLiteral *getAsmString() { return AsmString; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index b35d134..ce48187 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -62,6 +62,15 @@ public: namespace clang { + /// \brief Captures the result of checking the availability of a + /// declaration. + enum AvailabilityResult { + AR_Available = 0, + AR_NotYetIntroduced, + AR_Deprecated, + AR_Unavailable + }; + /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. /// @@ -147,9 +156,20 @@ public: IDNS_NonMemberOperator = 0x0400 }; - /// ObjCDeclQualifier - Qualifier used on types in method declarations - /// for remote messaging. They are meant for the arguments though and - /// applied to the Decls (ObjCMethodDecl and ParmVarDecl). + /// ObjCDeclQualifier - 'Qualifiers' written next to the return and + /// parameter types in method declarations. Other than remembering + /// them and mangling them into the method's signature string, these + /// are ignored by the compiler; they are consumed by certain + /// remote-messaging frameworks. + /// + /// in, inout, and out are mutually exclusive and apply only to + /// method parameters. bycopy and byref are mutually exclusive and + /// apply only to method parameters (?). oneway applies only to + /// results. All of these expect their corresponding parameter to + /// have a particular type. None of this is currently enforced by + /// clang. + /// + /// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier. enum ObjCDeclQualifier { OBJC_TQ_None = 0x0, OBJC_TQ_In = 0x1, @@ -218,6 +238,12 @@ private: /// required. unsigned Used : 1; + /// \brief Whether this declaration was "referenced". + /// The difference with 'Used' is whether the reference appears in a + /// evaluated context or not, e.g. functions used in uninstantiated templates + /// are regarded as "referenced" but not "used". + unsigned Referenced : 1; + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum @@ -252,7 +278,7 @@ protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -262,7 +288,7 @@ protected: Decl(Kind DK, EmptyShell Empty) : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -399,6 +425,57 @@ public: void setUsed(bool U = true) { Used = U; } + /// \brief Whether this declaration was referenced. + bool isReferenced() const; + + void setReferenced(bool R = true) { Referenced = R; } + + /// \brief Determine the availability of the given declaration. + /// + /// This routine will determine the most restrictive availability of + /// the given declaration (e.g., preferring 'unavailable' to + /// 'deprecated'). + /// + /// \param Message If non-NULL and the result is not \c + /// AR_Available, will be set to a (possibly empty) message + /// describing why the declaration has not been introduced, is + /// deprecated, or is unavailable. + AvailabilityResult getAvailability(std::string *Message = 0) const; + + /// \brief Determine whether this declaration is marked 'deprecated'. + /// + /// \param Message If non-NULL and the declaration is deprecated, + /// this will be set to the message describing why the declaration + /// was deprecated (which may be empty). + bool isDeprecated(std::string *Message = 0) const { + return getAvailability(Message) == AR_Deprecated; + } + + /// \brief Determine whether this declaration is marked 'unavailable'. + /// + /// \param Message If non-NULL and the declaration is unavailable, + /// this will be set to the message describing why the declaration + /// was made unavailable (which may be empty). + bool isUnavailable(std::string *Message = 0) const { + return getAvailability(Message) == AR_Unavailable; + } + + /// \brief Determine whether this is a weak-imported symbol. + /// + /// Weak-imported symbols are typically marked with the + /// 'weak_import' attribute, but may also be marked with an + /// 'availability' attribute where we're targing a platform prior to + /// the introduction of this feature. + bool isWeakImported() const; + + /// \brief Determines whether this symbol can be weak-imported, + /// e.g., whether it would be well-formed to add the weak_import + /// attribute. + /// + /// \param IsDefinition Set to \c true to indicate that this + /// declaration cannot be weak-imported because it has a definition. + bool canBeWeakImported(bool &IsDefinition) const; + /// \brief Retrieve the level of precompiled header from which this /// declaration was generated. /// diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 1656a7e..8c819e3 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -306,6 +306,37 @@ class CXXRecordDecl : public RecordDecl { /// one pure virtual function, (that can come from a base class). bool Abstract : 1; + /// IsStandardLayout - True when this class has standard layout. + /// + /// C++0x [class]p7. A standard-layout class is a class that: + /// * has no non-static data members of type non-standard-layout class (or + /// array of such types) or reference, + /// * has no virtual functions (10.3) and no virtual base classes (10.1), + /// * has the same access control (Clause 11) for all non-static data members + /// * has no non-standard-layout base classes, + /// * either has no non-static data members in the most derived class and at + /// most one base class with non-static data members, or has no base + /// classes with non-static data members, and + /// * has no base classes of the same type as the first non-static data + /// member. + bool IsStandardLayout : 1; + + /// HasNoNonEmptyBases - True when there are no non-empty base classes. + /// + /// This is a helper bit of state used to implement IsStandardLayout more + /// efficiently. + bool HasNoNonEmptyBases : 1; + + /// HasPrivateFields - True when there are private non-static data members. + bool HasPrivateFields : 1; + + /// HasProtectedFields - True when there are protected non-static data + /// members. + bool HasProtectedFields : 1; + + /// HasPublicFields - True when there are private non-static data members. + bool HasPublicFields : 1; + /// HasTrivialConstructor - True when this class has a trivial constructor. /// /// C++ [class.ctor]p5. A constructor is trivial if it is an @@ -316,31 +347,71 @@ class CXXRecordDecl : public RecordDecl { /// (or array thereof), each such class has a trivial constructor. bool HasTrivialConstructor : 1; + /// HasConstExprNonCopyMoveConstructor - True when this class has at least + /// one constexpr constructor which is neither the copy nor move + /// constructor. + bool HasConstExprNonCopyMoveConstructor : 1; + /// HasTrivialCopyConstructor - True when this class has a trivial copy /// constructor. /// - /// C++ [class.copy]p6. A copy constructor for class X is trivial - /// if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy constructor, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy constructor; - /// otherwise the copy constructor is non-trivial. + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. bool HasTrivialCopyConstructor : 1; + /// HasTrivialMoveConstructor - True when this class has a trivial move + /// constructor. + /// + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. + bool HasTrivialMoveConstructor : 1; + /// HasTrivialCopyAssignment - True when this class has a trivial copy /// assignment operator. /// - /// C++ [class.copy]p11. A copy assignment operator for class X is - /// trivial if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy assignment operator, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy assignment - /// operator; - /// otherwise the copy assignment operator is non-trivial. + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. bool HasTrivialCopyAssignment : 1; + /// HasTrivialMoveAssignment - True when this class has a trivial move + /// assignment operator. + /// + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. + bool HasTrivialMoveAssignment : 1; + /// HasTrivialDestructor - True when this class has a trivial destructor. /// /// C++ [class.dtor]p3. A destructor is trivial if it is an @@ -351,6 +422,10 @@ class CXXRecordDecl : public RecordDecl { /// type (or array thereof), each such class has a trivial destructor. bool HasTrivialDestructor : 1; + /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least + /// one non-static data member or base class of non literal type. + bool HasNonLiteralTypeFieldsOrBases : 1; + /// ComputedVisibleConversions - True when visible conversion functions are /// already computed and are available. bool ComputedVisibleConversions : 1; @@ -449,9 +524,8 @@ class CXXRecordDecl : public RecordDecl { protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - CXXRecordDecl *PrevDecl, - SourceLocation TKL = SourceLocation()); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl *PrevDecl); public: /// base_class_iterator - Iterator that traverses the base classes @@ -494,9 +568,8 @@ public: bool hasDefinition() const { return DefinitionData != 0; } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - CXXRecordDecl* PrevDecl=0, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -723,26 +796,58 @@ public: /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return data().Abstract; } + /// isStandardLayout - Whether this class has standard layout + /// (C++ [class]p7) + bool isStandardLayout() const { return data().IsStandardLayout; } + // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } + // hasConstExprNonCopyMoveConstructor - Whether this class has at least one + // constexpr constructor other than the copy or move constructors + bool hasConstExprNonCopyMoveConstructor() const { + return data().HasConstExprNonCopyMoveConstructor; + } + // hasTrivialCopyConstructor - Whether this class has a trivial copy - // constructor (C++ [class.copy]p6) + // constructor (C++ [class.copy]p6, C++0x [class.copy]p13) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } + // hasTrivialMoveConstructor - Whether this class has a trivial move + // constructor (C++0x [class.copy]p13) + bool hasTrivialMoveConstructor() const { + return data().HasTrivialMoveConstructor; + } + // hasTrivialCopyAssignment - Whether this class has a trivial copy - // assignment operator (C++ [class.copy]p11) + // assignment operator (C++ [class.copy]p11, C++0x [class.copy]p27) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } + // hasTrivialMoveAssignment - Whether this class has a trivial move + // assignment operator (C++0x [class.copy]p27) + bool hasTrivialMoveAssignment() const { + return data().HasTrivialMoveAssignment; + } + // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type + // non-static data member or base class. + bool hasNonLiteralTypeFieldsOrBases() const { + return data().HasNonLiteralTypeFieldsOrBases; + } + + // isTriviallyCopyable - Whether this class is considered trivially copyable + // (C++0x [class]p5). + bool isTriviallyCopyable() const; + /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -1034,20 +1139,27 @@ public: /// struct/union/class. class CXXMethodDecl : public FunctionDecl { protected: - CXXMethodDecl(Kind DK, CXXRecordDecl *RD, + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline) - : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None), - SCAsWritten, isInline) {} + bool isStatic, StorageClass SCAsWritten, bool isInline, + SourceLocation EndLocation) + : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, + (isStatic ? SC_Static : SC_None), + SCAsWritten, isInline) { + if (EndLocation.isValid()) + setRangeEnd(EndLocation); + } public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic = false, - StorageClass SCAsWritten = SC_None, - bool isInline = false); + bool isStatic, + StorageClass SCAsWritten, + bool isInline, + SourceLocation EndLocation); bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } @@ -1148,13 +1260,16 @@ public: /// @endcode class CXXCtorInitializer { /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being - /// initialized. - llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> + /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target + /// constructor (CXXConstructorDecl*) being initialized. + llvm::PointerUnion4<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *, + CXXConstructorDecl *> Initializee; /// \brief The source location for the field name or, for a base initializer - /// pack expansion, the location of the ellipsis. + /// pack expansion, the location of the ellipsis. In the case of a delegating + /// constructor, it will still include the type's source location as the + /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; /// \brief The argument used to initialize the base or member, which may @@ -1199,11 +1314,17 @@ public: SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new delegating Initializer. + explicit + CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, @@ -1227,6 +1348,12 @@ public: return Initializee.is<IndirectFieldDecl*>(); } + /// isDelegatingInitializer - Returns true when this initializer is creating + /// a delegating constructor. + bool isDelegatingInitializer() const { + return Initializee.is<CXXConstructorDecl *>(); + } + /// \brief Determine whether this initializer is a pack expansion. bool isPackExpansion() const { return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); @@ -1284,6 +1411,13 @@ public: return 0; } + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingInitializer()) + return Initializee.get<CXXConstructorDecl*>(); + else + return 0; + } + SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } @@ -1373,12 +1507,13 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXCtorInitializer **CtorInitializers; unsigned NumCtorInitializers; - CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1387,6 +1522,7 @@ class CXXConstructorDecl : public CXXMethodDecl { public: static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, @@ -1472,6 +1608,23 @@ public: void setCtorInitializers(CXXCtorInitializer ** initializers) { CtorInitializers = initializers; } + + /// isDelegatingConstructor - Whether this constructor is a + /// delegating constructor + bool isDelegatingConstructor() const { + return (getNumCtorInitializers() == 1) && + CtorInitializers[0]->isDelegatingInitializer(); + } + + /// getTargetConstructor - When this constructor delegates to + /// another, retrieve the target + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingConstructor()) + return CtorInitializers[0]->getTargetConstructor(); + else + return 0; + } + /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. @@ -1508,8 +1661,11 @@ public: /// \brief Determine whether this constructor is a move constructor /// (C++0x [class.copy]p3), which can be used to move values of the class. - bool isMoveConstructor() const; - + bool isMoveConstructor() const { + unsigned TypeQuals = 0; + return isMoveConstructor(TypeQuals); + } + /// \brief Determine whether this is a copy or move constructor. /// /// \param TypeQuals Will be set to the type qualifiers on the reference @@ -1567,11 +1723,12 @@ class CXXDestructorDecl : public CXXMethodDecl { FunctionDecl *OperatorDelete; - CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1579,6 +1736,7 @@ class CXXDestructorDecl : public CXXMethodDecl { public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo* TInfo, bool isInline, @@ -1629,19 +1787,23 @@ class CXXConversionDecl : public CXXMethodDecl { /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + bool isInline, bool isExplicitSpecified, + SourceLocation EndLocation) + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit); + bool isInline, bool isExplicit, + SourceLocation EndLocation); /// IsExplicitSpecified - Whether this conversion function declaration is /// marked "explicit", meaning that it can only be applied when the user @@ -1688,33 +1850,48 @@ public: private: /// Language - The language for this linkage specification. LanguageIDs Language; + /// ExternLoc - The source location for the extern keyword. + SourceLocation ExternLoc; + /// RBraceLoc - The source location for the right brace (if valid). + SourceLocation RBraceLoc; - /// HadBraces - Whether this linkage specification had curly braces or not. - bool HadBraces : 1; - - LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, - bool Braces) - : Decl(LinkageSpec, DC, L), - DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } + LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs lang, + SourceLocation RBLoc) + : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), + Language(lang), ExternLoc(ExternLoc), RBraceLoc(RBLoc) { } public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, LanguageIDs Lang, - bool Braces); + SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs Lang, + SourceLocation RBraceLoc = SourceLocation()); /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } - /// \brief Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } /// \brief Determines whether this linkage specification had braces in /// its syntactic form. - bool hasBraces() const { return HadBraces; } + bool hasBraces() const { return RBraceLoc.isValid(); } - /// \brief Set whether this linkage specification has braces in its - /// syntactic form. - void setHasBraces(bool B) { HadBraces = B; } + SourceLocation getExternLoc() const { return ExternLoc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setExternLoc(SourceLocation L) { ExternLoc = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getLocEnd() const { + if (hasBraces()) + return getRBraceLoc(); + // No braces: get the end location of the (only) declaration in context + // (if present). + return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); + } + + SourceRange getSourceRange() const { + return SourceRange(ExternLoc, getLocEnd()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LinkageSpecDecl *D) { return true; } @@ -2023,12 +2200,6 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2154,12 +2325,6 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2205,15 +2370,15 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, IdentifierInfo *TargetName) - : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), - UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), - QualifierLoc(QualifierLoc) { } + : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, + UsingLoc), + TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; public: /// \brief Returns the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } + SourceLocation getUsingLoc() const { return getLocStart(); } /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } @@ -2227,22 +2392,11 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - - // FIXME: DeclarationNameInfo static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, 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; } @@ -2252,15 +2406,19 @@ public: class StaticAssertDecl : public Decl { Expr *AssertExpr; StringLiteral *Message; + SourceLocation RParenLoc; - StaticAssertDecl(DeclContext *DC, SourceLocation L, - Expr *assertexpr, StringLiteral *message) - : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { } + StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, + Expr *assertexpr, StringLiteral *message, + SourceLocation RParenLoc) + : Decl(StaticAssert, DC, StaticAssertLoc), AssertExpr(assertexpr), + Message(message), RParenLoc(RParenLoc) { } public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, Expr *AssertExpr, - StringLiteral *Message); + SourceLocation StaticAssertLoc, + Expr *AssertExpr, StringLiteral *Message, + SourceLocation RParenLoc); Expr *getAssertExpr() { return AssertExpr; } const Expr *getAssertExpr() const { return AssertExpr; } @@ -2268,6 +2426,13 @@ public: StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(getLocation(), getRParenLoc()); + } + 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; } diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 20d6da1..b84e5bb 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -98,6 +98,17 @@ public: return FriendLoc; } + /// Retrieves the source range for the friend declaration. + SourceRange getSourceRange() const { + /* FIXME: consider the case of templates wrt start of range. */ + if (NamedDecl *ND = getFriendDecl()) + return SourceRange(getFriendLoc(), ND->getLocEnd()); + else if (TypeSourceInfo *TInfo = getFriendType()) + return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc()); + else + return SourceRange(getFriendLoc(), getLocation()); + } + /// Determines if this friend kind is unsupported. bool isUnsupportedFriend() const { return UnsupportedFriend; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index b3ca474..0a4d864 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -112,17 +112,20 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { public: enum ImplementationControl { None, Required, Optional }; private: - /// Bitfields must be first fields in this class so they pack with those - /// declared in class Decl. + // The conventional meaning of this method; an ObjCMethodFamily. + // This is not serialized; instead, it is computed on demand and + // cached. + mutable unsigned Family : ObjCMethodFamilyBitWidth; + /// instance (true) or class (false) method. - bool IsInstance : 1; - bool IsVariadic : 1; + unsigned IsInstance : 1; + unsigned IsVariadic : 1; // Synthesized declaration method for a property setter/getter - bool IsSynthesized : 1; + unsigned IsSynthesized : 1; // Method has a definition. - bool IsDefined : 1; + unsigned IsDefined : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional @@ -170,7 +173,7 @@ private: ImplementationControl impControl = None, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), + DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), IsDefined(isDefined), @@ -279,6 +282,9 @@ public: ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } + /// Determines the family of this method. + ObjCMethodFamily getMethodFamily() const; + bool isInstanceMethod() const { return IsInstance; } void setInstanceMethod(bool isInst) { IsInstance = isInst; } bool isVariadic() const { return IsVariadic; } @@ -453,7 +459,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// /// Categories are stored as a linked list in the AST, since the categories /// and class extensions come long after the initial interface declaration, - /// and we avoid dynamically-resized arrays in the AST whereever possible. + /// and we avoid dynamically-resized arrays in the AST wherever possible. ObjCCategoryDecl *CategoryList; /// IvarList - List of all ivars defined by this class; including class @@ -701,15 +707,18 @@ public: }; private: - ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, + ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) - : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} + : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, + /*Mutable=*/false), + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL, bool synthesized=false); @@ -753,17 +762,18 @@ private: /// @defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { private: - ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, L, Id, T, + : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? BW, /*Mutable=*/false) {} public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, QualType T, - Expr *BW); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, Expr *BW); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -773,7 +783,7 @@ public: /// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols /// declare a pure abstract type (i.e no instance variables are permitted). -/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ +/// Protocols originally drew inspiration from C++ pure virtual functions (a C++ /// feature with nice semantics and lousy syntax:-). Here is an example: /// /// @protocol NSDraggingInfo <refproto1, refproto2> diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f41859c..ddbe344 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -771,9 +771,20 @@ protected: /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { + Common() : InjectedArgs(0) { } + /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + + /// \brief The set of "injected" template arguments used within this + /// function template. + /// + /// This pointer refers to the template arguments (there are as + /// many template arguments as template parameaters) for the function + /// template, and is allocated lazily, since most function templates do not + /// require the use of this information. + TemplateArgument *InjectedArgs; }; FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -793,6 +804,13 @@ protected: llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { return getCommonPtr()->Specializations; } + + /// \brief Add a specialization of this function template. + /// + /// \param InsertPos Insert position in the FoldingSet, must have been + /// retrieved by an earlier call to findSpecialization(). + void addSpecialization(FunctionTemplateSpecializationInfo* Info, + void *InsertPos); public: /// Get the underlying function declaration of the template. @@ -844,13 +862,25 @@ public: return makeSpecIterator(getSpecializations(), true); } - /// Create a template function node. + /// \brief Retrieve the "injected" template arguments that correspond to the + /// template parameters of this function template. + /// + /// Although the C++ standard has no notion of the "injected" template + /// arguments for a function template, the notion is convenient when + /// we need to perform substitutions inside the definition of a function + /// template. + std::pair<const TemplateArgument *, unsigned> getInjectedTemplateArgs(); + + /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); + /// \brief Create an empty function template node. + static FunctionTemplateDecl *Create(ASTContext &C, EmptyShell); + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionTemplateDecl *D) { return true; } @@ -915,25 +945,23 @@ class TemplateTypeParmDecl : public TypeDecl { /// default argument. bool InheritedDefault : 1; - /// \brief Whether this is a parameter pack. - bool ParameterPack : 1; - /// \brief The default template argument, if any. TypeSourceInfo *DefaultArgument; - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - bool Typename, QualType Type, bool ParameterPack) - : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), - InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { - TypeForDecl = Type.getTypePtrOrNull(); - } + TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + bool Typename) + : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), + InheritedDefault(false), DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, + SourceLocation KeyLoc, + SourceLocation NameLoc, + unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -978,9 +1006,6 @@ public: /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - /// \brief Set whether this is a parameter pack. - void setParameterPack(bool isParamPack) { ParameterPack = isParamPack; } - /// \brief Retrieve the depth of the template parameter. unsigned getDepth() const; @@ -988,7 +1013,9 @@ public: unsigned getIndex() const; /// \brief Returns whether this is a parameter pack. - bool isParameterPack() const { return ParameterPack; } + bool isParameterPack() const; + + SourceRange getSourceRange() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1021,17 +1048,19 @@ class NonTypeTemplateParmDecl /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) - : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedTypes(0) { } - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, @@ -1041,13 +1070,14 @@ class NonTypeTemplateParmDecl public: static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, - TypeSourceInfo *TInfo); + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, bool ParameterPack, TypeSourceInfo *TInfo); static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos); @@ -1057,7 +1087,6 @@ public: using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - SourceLocation getInnerLocStart() const; SourceRange getSourceRange() const; /// \brief Determine whether this template parameter has a default @@ -1316,7 +1345,8 @@ class ClassTemplateSpecializationDecl protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1326,7 +1356,8 @@ protected: public: static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1488,7 +1519,7 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); } + SourceRange getSourceRange() const; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); @@ -1544,7 +1575,9 @@ class ClassTemplatePartialSpecializationDecl InstantiatedFromMember; ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1552,14 +1585,7 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, L, SpecializedTemplate, - Args, NumArgs, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), - InstantiatedFromMember(0, false) { } + unsigned SequenceNumber); ClassTemplatePartialSpecializationDecl() : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), @@ -1569,7 +1595,8 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1742,6 +1769,10 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + ClassTemplateDecl(EmptyShell Empty) + : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(), + DeclarationName(), 0, 0) { } + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { @@ -1768,6 +1799,9 @@ public: NamedDecl *Decl, ClassTemplateDecl *PrevDecl); + /// Create an empty class template node. + static ClassTemplateDecl *Create(ASTContext &C, EmptyShell); + /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. ClassTemplateSpecializationDecl * diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 035f57c..bab1606 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -37,7 +37,8 @@ public: // other sub-expressions). void VisitDeclRefExpr(DeclRefExpr *E) { } void VisitOffsetOfExpr(OffsetOfExpr *E) { } - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { } + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { } + void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { } void VisitBlockExpr(BlockExpr *E) { } void VisitCXXUuidofExpr(CXXUuidofExpr *E) { } void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 95bfad5..5f2d144 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -21,12 +21,12 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/UsuallyTinyPtrVector.h" +#include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include <cctype> -#include <vector> namespace clang { class ASTContext; @@ -172,6 +172,7 @@ public: LV_IncompleteVoidType, LV_DuplicateVectorComponents, LV_InvalidExpression, + LV_InvalidMessageExpression, LV_MemberFunction, LV_SubObjCPropertySetting, LV_ClassTemporary @@ -203,6 +204,7 @@ public: MLV_NoSetterProperty, MLV_MemberFunction, MLV_SubObjCPropertySetting, + MLV_InvalidMessageExpression, MLV_ClassTemporary }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, @@ -218,10 +220,12 @@ public: CL_XValue, CL_Function, // Functions cannot be lvalues in C. CL_Void, // Void cannot be an lvalue in C. + CL_AddressableVoid, // Void expression whose address can be taken in C. CL_DuplicateVectorComponents, // A vector shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, CL_ClassTemporary, // A prvalue of class type + CL_ObjCMessageRValue, // ObjC message is an rvalue CL_PRValue // A prvalue for any other reason, of any other type }; /// \brief The results of modification testing. @@ -482,6 +486,11 @@ public: /// \brief Returns true if this expression is a bound member function. bool isBoundMemberFunction(ASTContext &Ctx) const; + /// \brief Given an expression of bound-member type, find the type + /// of the member. Returns null if this is an *overloaded* bound + /// member expression. + static QualType findBoundMemberType(const Expr *expr); + /// \brief Result type of CanThrow(). enum CanThrowResult { CT_Cannot, @@ -536,6 +545,9 @@ public: /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; + /// \brief Whether this expression is an implicit reference to 'this' in C++. + bool isImplicitCXXThis() const; + const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } @@ -618,16 +630,6 @@ public: static bool classof(const OpaqueValueExpr *) { return true; } }; -/// \brief Represents the qualifier that may precede a C++ name, e.g., the -/// "std::" in "std::sort". -struct NameQualifier { - /// \brief The nested name specifier. - NestedNameSpecifier *NNS; - - /// \brief The source range covered by the nested name specifier. - SourceRange Range; -}; - /// \brief Represents an explicit template argument list in C++, e.g., /// the "<int>" in "sort<int>". struct ExplicitTemplateArgumentList { @@ -659,95 +661,118 @@ struct ExplicitTemplateArgumentList { static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; - -/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, -/// enum, etc. + +/// \brief A reference to a declared variable, function, enum, etc. +/// [C99 6.5.1p2] +/// +/// This encodes all the information about how a declaration is referenced +/// within an expression. +/// +/// There are several optional constructs attached to DeclRefExprs only when +/// they apply in order to conserve memory. These are laid out past the end of +/// the object, and flags in the DeclRefExprBitfield track whether they exist: +/// +/// DeclRefExprBits.HasQualifier: +/// Specifies when this declaration reference expression has a C++ +/// nested-name-specifier. +/// DeclRefExprBits.HasFoundDecl: +/// Specifies when this declaration reference expression has a record of +/// a NamedDecl (different from the referenced ValueDecl) which was found +/// during name lookup and/or overload resolution. +/// DeclRefExprBits.HasExplicitTemplateArgs: +/// Specifies when this declaration reference expression has an explicit +/// C++ template argument list. class DeclRefExpr : public Expr { - enum { - // Flag on DecoratedD that specifies when this declaration reference - // expression has a C++ nested-name-specifier. - HasQualifierFlag = 0x01, - // Flag on DecoratedD that specifies when this declaration reference - // expression has an explicit C++ template argument list. - HasExplicitTemplateArgumentListFlag = 0x02 - }; - - // DecoratedD - The declaration that we are referencing, plus two bits to - // indicate whether (1) the declaration's name was explicitly qualified and - // (2) the declaration's name was followed by an explicit template - // argument list. - llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; + /// \brief The declaration that we are referencing. + ValueDecl *D; - // Loc - The location of the declaration name itself. + /// \brief The location of the declaration name itself. SourceLocation Loc; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in DecoratedD. + /// \brief Provides source/type location info for the declaration name + /// embedded in D. DeclarationNameLoc DNLoc; - /// \brief Retrieve the qualifier that preceded the declaration name, if any. - NameQualifier *getNameQualifier() { - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return 0; - - return reinterpret_cast<NameQualifier *> (this + 1); + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + NestedNameSpecifierLoc &getInternalQualifierLoc() { + assert(hasQualifier()); + return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1); } - - /// \brief Retrieve the qualifier that preceded the member name, if any. - const NameQualifier *getNameQualifier() const { - return const_cast<DeclRefExpr *>(this)->getNameQualifier(); + + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + const NestedNameSpecifierLoc &getInternalQualifierLoc() const { + return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc(); } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - ValueDecl *D, SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK); + /// \brief Test whether there is a distinct FoundDecl attached to the end of + /// this DRE. + bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *&getInternalFoundDecl() { + assert(hasFoundDecl()); + if (hasQualifier()) + return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1); + return *reinterpret_cast<NamedDecl **>(this + 1); + } + + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *getInternalFoundDecl() const { + return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl(); + } + + DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - + /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. void computeDependence(); public: - DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) : - Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false), - DecoratedD(d, 0), Loc(l) { + DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), + D(D), Loc(L) { + DeclRefExprBits.HasQualifier = 0; + DeclRefExprBits.HasExplicitTemplateArgs = 0; + DeclRefExprBits.HasFoundDecl = 0; computeDependence(); } static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, SourceLocation NameLoc, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, - bool HasQualifier, + bool HasQualifier, + bool HasFoundDecl, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs); - - ValueDecl *getDecl() { return DecoratedD.getPointer(); } - const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } - void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + + ValueDecl *getDecl() { return D; } + const ValueDecl *getDecl() const { return D; } + void setDecl(ValueDecl *NewD) { D = NewD; } DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); @@ -759,43 +784,62 @@ public: /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. - bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } - - /// \brief If the name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!hasQualifier()) - return SourceRange(); - - return getNameQualifier()->Range; - } - - /// \brief If the name was qualified, retrieves the nested-name-specifier + bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } + + /// \brief If the name was qualified, retrieves the nested-name-specifier /// that precedes the name. Otherwise, returns NULL. NestedNameSpecifier *getQualifier() const { if (!hasQualifier()) return 0; - - return getNameQualifier()->NNS; + + return getInternalQualifierLoc().getNestedNameSpecifier(); } - + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name, with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getInternalQualifierLoc(); + } + + /// \brief Get the NamedDecl through which this reference occured. + /// + /// This Decl may be different from the ValueDecl actually referred to in the + /// presence of using declarations, etc. It always returns non-NULL, and may + /// simple return the ValueDecl when appropriate. + NamedDecl *getFoundDecl() { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Get the NamedDecl through which this reference occurred. + /// See non-const variant. + const NamedDecl *getFoundDecl() const { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Determines whether this declaration reference was followed by an + /// explict template argument list. bool hasExplicitTemplateArgs() const { - return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag); + return DeclRefExprBits.HasExplicitTemplateArgs; } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. ExplicitTemplateArgumentList &getExplicitTemplateArgs() { assert(hasExplicitTemplateArgs()); + if (hasFoundDecl()) + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + &getInternalFoundDecl() + 1); - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return *reinterpret_cast<ExplicitTemplateArgumentList *>( - getNameQualifier() + 1); + if (hasQualifier()) + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + &getInternalQualifierLoc() + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { @@ -809,50 +853,50 @@ public: if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } - + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) getExplicitTemplateArgs().copyInto(List); } - + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().LAngleLoc; } - + /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().getTemplateArgs(); } - + /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().NumTemplateArgs; } - + /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().RAngleLoc; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -860,7 +904,7 @@ public: // Iterators child_range children() { return child_range(); } - + friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -1133,9 +1177,12 @@ public: /// In this case, getByteLength() will return 6, but the string literal will /// have type "char[2]". class StringLiteral : public Expr { + friend class ASTStmtReader; + const char *StrData; unsigned ByteLength; bool IsWide; + bool IsPascal; unsigned NumConcatenated; SourceLocation TokLocs[1]; @@ -1146,14 +1193,15 @@ public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, bool Wide, QualType Ty, + unsigned ByteLength, bool Wide, bool Pascal, + QualType Ty, const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, - bool Wide, QualType Ty, SourceLocation Loc) { - return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1); + unsigned ByteLength, bool Wide, + bool Pascal, QualType Ty, SourceLocation Loc) { + return Create(C, StrData, ByteLength, Wide, Pascal, Ty, &Loc, 1); } /// \brief Construct an empty string literal. @@ -1169,8 +1217,8 @@ public: void setString(ASTContext &C, llvm::StringRef Str); bool isWide() const { return IsWide; } - void setWide(bool W) { IsWide = W; } - + bool isPascal() const { return IsPascal; } + bool containsNonAsciiOrNull() const { llvm::StringRef Str = getString(); for (unsigned i = 0, e = Str.size(); i != e; ++i) @@ -1458,7 +1506,7 @@ public: /// the square brackets. For a field or identifier node, the source range /// contains the location of the period (if there is one) and the /// identifier. - SourceRange getRange() const { return Range; } + SourceRange getSourceRange() const { return Range; } }; private: @@ -1556,10 +1604,11 @@ public: } }; -/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of -/// types and expressions. -class SizeOfAlignOfExpr : public Expr { - bool isSizeof : 1; // true if sizeof, false if alignof. +/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) +/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and +/// vec_step (OpenCL 1.1 6.11.12). +class UnaryExprOrTypeTraitExpr : public Expr { + unsigned Kind : 2; bool isType : 1; // true if operand is a type, false if an expression union { TypeSourceInfo *Ty; @@ -1568,36 +1617,38 @@ class SizeOfAlignOfExpr : public Expr { SourceLocation OpLoc, RParenLoc; public: - SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. TInfo->getType()->isDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { Argument.Ty = TInfo; } - SizeOfAlignOfExpr(bool issizeof, Expr *E, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. E->isTypeDependent(), E->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { Argument.Ex = E; } /// \brief Construct an empty sizeof/alignof expression. - explicit SizeOfAlignOfExpr(EmptyShell Empty) - : Expr(SizeOfAlignOfExprClass, Empty) { } + explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) + : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } - bool isSizeOf() const { return isSizeof; } - void setSizeof(bool S) { isSizeof = S; } + UnaryExprOrTypeTrait getKind() const { + return static_cast<UnaryExprOrTypeTrait>(Kind); + } + void setKind(UnaryExprOrTypeTrait K) { Kind = K; } bool isArgumentType() const { return isType; } QualType getArgumentType() const { @@ -1612,7 +1663,7 @@ public: return static_cast<Expr*>(Argument.Ex); } const Expr *getArgumentExpr() const { - return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr(); + return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } @@ -1638,9 +1689,9 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == SizeOfAlignOfExprClass; + return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; } - static bool classof(const SizeOfAlignOfExpr *) { return true; } + static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; } // Iterators child_range children(); @@ -1862,7 +1913,13 @@ public: /// class MemberExpr : public Expr { /// Extra data stored in some member expressions. - struct MemberNameQualifier : public NameQualifier { + struct MemberNameQualifier { + /// \brief The nested-name-specifier that qualifies the name, including + /// source-location information. + NestedNameSpecifierLoc QualifierLoc; + + /// \brief The DeclAccessPair through which the MemberDecl was found due to + /// name qualifiers. DeclAccessPair FoundDecl; }; @@ -1936,7 +1993,7 @@ public: HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifier *qual, SourceRange qualrange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, @@ -1965,16 +2022,6 @@ public: /// x->Base::foo. bool hasQualifier() const { return getQualifier() != 0; } - /// \brief If the member name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the member name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!HasQualifierOrFoundDecl) - return SourceRange(); - - return getMemberQualifier()->Range; - } - /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. @@ -1982,7 +2029,17 @@ public: if (!HasQualifierOrFoundDecl) return 0; - return getMemberQualifier()->NNS; + return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name, with source-location + /// information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getMemberQualifier()->QualifierLoc; } /// \brief Determines whether this member expression actually had a C++ @@ -2075,20 +2132,15 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const { - // If we have an implicit base (like a C++ implicit this), - // make sure not to return its location - SourceLocation EndLoc = (HasExplicitTemplateArgumentList) - ? getRAngleLoc() : getMemberNameInfo().getEndLoc(); - - SourceLocation BaseLoc = getBase()->getLocStart(); - if (BaseLoc.isInvalid()) - return SourceRange(MemberLoc, EndLoc); - return SourceRange(BaseLoc, EndLoc); - } - + SourceRange getSourceRange() const; + SourceLocation getExprLoc() const { return MemberLoc; } + /// \brief Determine whether the base of this explicit is implicit. + bool isImplicitAccess() const { + return getBase() && getBase()->isImplicitCXXThis(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } @@ -2234,6 +2286,12 @@ private: } CXXBaseSpecifier **path_buffer(); + void setBasePathSize(unsigned basePathSize) { + CastExprBits.BasePathSize = basePathSize; + assert(CastExprBits.BasePathSize == basePathSize && + "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); + } + protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, Expr *op, unsigned BasePathSize) : @@ -2249,14 +2307,14 @@ protected: Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); CheckCastConsistency(); } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); } public: @@ -3173,9 +3231,14 @@ class InitListExpr : public Expr { /// written in the source code. InitListExpr *SyntacticForm; - /// If this initializer list initializes a union, specifies which - /// field within the union will be initialized. - FieldDecl *UnionFieldInit; + /// \brief Either: + /// If this initializer list initializes an array with more elements than + /// there are initializers in the list, specifies an expression to be used + /// for value initialization of the rest of the elements. + /// Or + /// If this initializer list initializes a union, specifies which + /// field within the union will be initialized. + llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; /// Whether this initializer list originally had a GNU array-range /// designator in it. This is a temporary marker used by CodeGen. @@ -3227,17 +3290,29 @@ public: /// /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to - /// accomodate the new entry. + /// accommodate the new entry. Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); + /// \brief If this initializer list initializes an array with more elements + /// than there are initializers in the list, specifies an expression to be + /// used for value initialization of the rest of the elements. + Expr *getArrayFiller() { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + void setArrayFiller(Expr *filler); + /// \brief If this initializes a union, specifies which field in the /// union to initialize. /// /// Typically, this field is the first named field within the /// union. However, a designated initializer can specify the /// initialization of a different field within the union. - FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; } - void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; } + FieldDecl *getInitializedFieldInUnion() { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + void setInitializedFieldInUnion(FieldDecl *FD) { + ArrayFillerOrUnionFieldInit = FD; + } // Explicit InitListExpr's originate from source code (and have valid source // locations). Implicit InitListExpr's are created by the semantic analyzer. @@ -3288,6 +3363,9 @@ public: const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } reverse_iterator rend() { return InitExprs.rend(); } const_reverse_iterator rend() const { return InitExprs.rend(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// @brief Represents a C99 designated initializer expression. @@ -3492,6 +3570,12 @@ public: else return getLBracketLoc(); } + SourceLocation getEndLocation() const { + return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); + } + SourceRange getSourceRange() const { + return SourceRange(getStartLocation(), getEndLocation()); + } }; static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, @@ -3574,6 +3658,8 @@ public: void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last); + SourceRange getDesignatorsSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { @@ -3667,6 +3753,118 @@ public: }; +/// \brief Represents a C1X generic selection. +/// +/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling +/// expression, followed by one or more generic associations. Each generic +/// association specifies a type name and an expression, or "default" and an +/// expression (in which case it is known as a default generic association). +/// The type and value of the generic selection are identical to those of its +/// result expression, which is defined as the expression in the generic +/// association with a type name that is compatible with the type of the +/// controlling expression, or the expression in the default generic association +/// if no types are compatible. For example: +/// +/// @code +/// _Generic(X, double: 1, float: 2, default: 3) +/// @endcode +/// +/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f +/// or 3 if "hello". +/// +/// As an extension, generic selections are allowed in C++, where the following +/// additional semantics apply: +/// +/// Any generic selection whose controlling expression is type-dependent or +/// which names a dependent type in its association list is result-dependent, +/// which means that the choice of result expression is dependent. +/// Result-dependent generic associations are both type- and value-dependent. +class GenericSelectionExpr : public Expr { + enum { CONTROLLING, END_EXPR }; + TypeSourceInfo **AssocTypes; + Stmt **SubExprs; + unsigned NumAssocs, ResultIndex; + SourceLocation GenericLoc, DefaultLoc, RParenLoc; + +public: + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// This constructor is used in the result-dependent case. + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack); + + explicit GenericSelectionExpr(EmptyShell Empty) + : Expr(GenericSelectionExprClass, Empty) { } + + unsigned getNumAssocs() const { return NumAssocs; } + + SourceLocation getGenericLoc() const { return GenericLoc; } + SourceLocation getDefaultLoc() const { return DefaultLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + const Expr *getAssocExpr(unsigned i) const { + return cast<Expr>(SubExprs[END_EXPR+i]); + } + Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); } + + const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { + return AssocTypes[i]; + } + TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + + QualType getAssocType(unsigned i) const { + if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) + return TS->getType(); + else + return QualType(); + } + + const Expr *getControllingExpr() const { + return cast<Expr>(SubExprs[CONTROLLING]); + } + Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); } + + /// Whether this generic selection is result-dependent. + bool isResultDependent() const { return ResultIndex == -1U; } + + /// The zero-based index of the result expression's generic association in + /// the generic selection's association list. Defined only if the + /// generic selection is not result-dependent. + unsigned getResultIndex() const { + assert(!isResultDependent() && "Generic selection is result-dependent"); + return ResultIndex; + } + + /// The generic selection's result expression. Defined only if the + /// generic selection is not result-dependent. + const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } + Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } + + SourceRange getSourceRange() const { + return SourceRange(GenericLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GenericSelectionExprClass; + } + static bool classof(const GenericSelectionExpr *) { return true; } + + child_range children() { + return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); + } + + friend class ASTStmtReader; +}; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 225db3c..a970579 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/ExpressionTraits.h" #include "clang/AST/Expr.h" #include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" @@ -99,7 +100,10 @@ public: /// getImplicitObjectArgument - Retrieves the implicit object /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". - Expr *getImplicitObjectArgument(); + Expr *getImplicitObjectArgument() const; + + /// Retrieves the declaration of the called method. + CXXMethodDecl *getMethodDecl() const; /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of /// the implicit object argument. Note that this is may not be the same @@ -250,6 +254,8 @@ public: static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); + bool isAlwaysNull() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } @@ -774,7 +780,8 @@ public: enum ConstructionKind { CK_Complete, CK_NonVirtualBase, - CK_VirtualBase + CK_VirtualBase, + CK_Delegating }; private: @@ -1080,6 +1087,17 @@ public: TypeSourceInfo *getAllocatedTypeSourceInfo() const { return AllocatedTypeInfo; } + + /// \brief True if the allocation result needs to be null-checked. + /// C++0x [expr.new]p13: + /// If the allocation function returns null, initialization shall + /// not be done, the deallocation function shall not be called, + /// and the value of the new-expression shall be null. + /// An allocation function is not allowed to return null unless it + /// has a non-throwing exception-specification. The '03 rule is + /// identical except that the definition of a non-throwing + /// exception specification is just "is it throw()?". + bool shouldNullCheckAllocation(ASTContext &Ctx) const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } @@ -1577,6 +1595,122 @@ public: friend class ASTStmtReader; }; +/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the +/// implementation of __array_rank and __array_extent. +/// Example: +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +class ArrayTypeTraitExpr : public Expr { + /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + unsigned ATT : 2; + + /// The value of the type trait. Unspecified if dependent. + uint64_t Value; + + /// The array dimension being queried, or -1 if not used + Expr *Dimension; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// The type being queried. + TypeSourceInfo *QueriedType; + +public: + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, + TypeSourceInfo *queried, uint64_t value, + Expr *dimension, SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + queried->getType()->containsUnexpandedParameterPack()), + ATT(att), Value(value), Dimension(dimension), + Loc(loc), RParen(rparen), QueriedType(queried) { } + + + explicit ArrayTypeTraitExpr(EmptyShell Empty) + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), + QueriedType() { } + + virtual ~ArrayTypeTraitExpr() { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen); } + + ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } + + QualType getQueriedType() const { return QueriedType->getType(); } + + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + uint64_t getValue() const { assert(!isTypeDependent()); return Value; } + + Expr *getDimensionExpression() const { return Dimension; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArrayTypeTraitExprClass; + } + static bool classof(const ArrayTypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + +/// ExpressionTraitExpr - An expression trait intrinsic +/// Example: +/// __is_lvalue_expr(std::cout) == true +/// __is_lvalue_expr(1) == false +class ExpressionTraitExpr : public Expr { + /// ET - The trait. A ExpressionTrait enum in MSVC compat unsigned. + unsigned ET : 31; + /// The value of the type trait. Unspecified if dependent. + bool Value : 1; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + Expr* QueriedExpression; +public: + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, + Expr *queried, bool value, + SourceLocation rparen, QualType resultType) + : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Not type-dependent + // Value-dependent if the argument is type-dependent. + queried->isTypeDependent(), + queried->containsUnexpandedParameterPack()), + ET(et), Value(value), Loc(loc), RParen(rparen), QueriedExpression(queried) { } + + explicit ExpressionTraitExpr(EmptyShell Empty) + : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), + QueriedExpression() { } + + SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + + ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } + + Expr *getQueriedExpression() const { return QueriedExpression; } + + bool getValue() const { return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExpressionTraitExprClass; + } + static bool classof(const ExpressionTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + + /// \brief A reference to an overloaded function set, either an /// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. class OverloadExpr : public Expr { @@ -1590,18 +1724,15 @@ class OverloadExpr : public Expr { /// The common name of these declarations. DeclarationNameInfo NameInfo; - /// The scope specifier, if any. - NestedNameSpecifier *Qualifier; - - /// The source range of the scope specifier. - SourceRange QualifierRange; + /// \brief The nested-name-specifier that qualifies the name, if any. + NestedNameSpecifierLoc QualifierLoc; protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; OverloadExpr(StmtClass K, ASTContext &C, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, @@ -1610,7 +1741,7 @@ protected: OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty), Results(0), NumResults(0), - Qualifier(0), HasExplicitTemplateArgs(false) { } + QualifierLoc(), HasExplicitTemplateArgs(false) { } void initializeResults(ASTContext &C, UnresolvedSetIterator Begin, @@ -1665,23 +1796,21 @@ public: /// 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 NameInfo.getName(); } - void setName(DeclarationName N) { NameInfo.setName(N); } /// Gets the location of the name. 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; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } - /// Fetches the range of the nested-name qualifier. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// Fetches the nested-name qualifier with source-location information, if + /// one was given. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Determines whether this expression had an explicit /// template argument list, e.g. f<int>. @@ -1727,6 +1856,10 @@ class UnresolvedLookupExpr : public OverloadExpr { /// call. bool RequiresADL; + /// True if namespace ::std should be considered an associated namespace + /// for the purposes of argument-dependent lookup. See C++0x [stmt.ranged]p1. + bool StdIsAssociatedNamespace; + /// True if these lookup results are overloaded. This is pretty /// trivially rederivable if we urgently need to kill this field. bool Overloaded; @@ -1740,39 +1873,46 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool StdIsAssociatedNamespace) + : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, NameInfo, TemplateArgs, Begin, End), - RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) + RequiresADL(RequiresADL), + StdIsAssociatedNamespace(StdIsAssociatedNamespace), + Overloaded(Overloaded), NamingClass(NamingClass) {} UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(0) + RequiresADL(false), StdIsAssociatedNamespace(false), Overloaded(false), + NamingClass(0) {} + friend class ASTStmtReader; + public: static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier, - QualifierRange, NameInfo, ADL, - Overloaded, 0, Begin, End); + UnresolvedSetIterator End, + bool StdIsAssociatedNamespace = false) { + assert((ADL || !StdIsAssociatedNamespace) && + "std considered associated namespace when not performing ADL"); + return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, + ADL, Overloaded, 0, Begin, End, + StdIsAssociatedNamespace); } static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, @@ -1786,17 +1926,18 @@ public: /// True if this declaration should be extended by /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } - void setRequiresADL(bool V) { RequiresADL = V; } + + /// True if namespace ::std should be artificially added to the set of + /// associated namespaecs for argument-dependent lookup purposes. + bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; } /// True if this lookup is overloaded. bool isOverloaded() const { return Overloaded; } - void setOverloaded(bool V) { Overloaded = V; } /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. CXXRecordDecl *getNamingClass() const { return NamingClass; } - void setNamingClass(CXXRecordDecl *D) { NamingClass = D; } // Note that, inconsistently with the explicit-template-argument AST // nodes, users are *forbidden* from calling these methods on objects @@ -1845,8 +1986,10 @@ public: SourceRange getSourceRange() const { SourceRange Range(getNameInfo().getSourceRange()); - if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); - if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); return Range; } @@ -2186,16 +2329,13 @@ class CXXDependentScopeMemberExpr : public Expr { SourceLocation OperatorLoc; /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifier *Qualifier; - - /// \brief The source range covering the nested name specifier. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief In a qualified member access expression such as t->Base::f, this /// member stores the resolves of name lookup in the context of the member /// access expression, to be used at instantiation time. /// - /// FIXME: This member, along with the Qualifier and QualifierRange, could + /// FIXME: This member, along with the QualifierLoc, could /// be stuck into a structure that is optionally allocated at the end of /// the CXXDependentScopeMemberExpr, to save space in the common case. NamedDecl *FirstQualifierFoundInScope; @@ -2208,8 +2348,7 @@ class CXXDependentScopeMemberExpr : public Expr { CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2219,8 +2358,7 @@ public: Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo); @@ -2228,8 +2366,7 @@ public: Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2241,7 +2378,7 @@ public: /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2249,30 +2386,27 @@ public: assert(!isImplicitAccess()); return cast<Expr>(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - - /// \brief Retrieve the source range covering the nested-name-specifier - /// that qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. @@ -2287,26 +2421,20 @@ public: NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } - void setFirstQualifierFoundInScope(NamedDecl *D) { - FirstQualifierFoundInScope = D; - } /// \brief Retrieve the name of the member that this expression /// refers to. 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 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>. @@ -2376,7 +2504,7 @@ public: if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + Range.setBegin(getQualifierLoc().getBeginLoc()); else Range.setBegin(MemberNameInfo.getBeginLoc()); @@ -2438,8 +2566,7 @@ class UnresolvedMemberExpr : public OverloadExpr { UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2448,13 +2575,14 @@ class UnresolvedMemberExpr : public OverloadExpr { : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(0) { } + friend class ASTStmtReader; + public: static UnresolvedMemberExpr * Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2466,7 +2594,7 @@ public: /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2478,24 +2606,19 @@ public: assert(!isImplicitAccess()); return cast<Expr>(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether the lookup results contain an unresolved using /// declaration. bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } - void setHasUnresolvedUsing(bool V) { HasUnresolvedUsing = V; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieves the naming class of this lookup. CXXRecordDecl *getNamingClass() const; @@ -2503,17 +2626,14 @@ public: /// \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(); } - void setMemberName(DeclarationName N) { setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - void setMemberLoc(SourceLocation L) { setNameLoc(L); } /// \brief Retrieve the explicit template argument list that followed the /// member template name. @@ -2570,8 +2690,8 @@ public: SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); - else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + else if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 285efb7..8163923 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -337,6 +337,39 @@ public: QualType getSuperReceiverType() const { return QualType(Receiver.get<const Type*>(), 0); } + QualType getGetterResultType() const { + QualType ResultType; + if (isExplicitProperty()) { + const ObjCPropertyDecl *PDecl = getExplicitProperty(); + if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl()) + ResultType = Getter->getResultType(); + else + ResultType = getType(); + } else { + const ObjCMethodDecl *Getter = getImplicitPropertyGetter(); + ResultType = Getter->getResultType(); // with reference! + } + return ResultType; + } + + QualType getSetterArgType() const { + QualType ArgType; + if (isImplicitProperty()) { + const ObjCMethodDecl *Setter = getImplicitPropertySetter(); + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } else { + if (ObjCPropertyDecl *PDecl = getExplicitProperty()) + if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) { + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } + if (ArgType.isNull()) + ArgType = getType(); + } + return ArgType; + } + ObjCInterfaceDecl *getClassReceiver() const { return Receiver.get<ObjCInterfaceDecl*>(); } @@ -741,6 +774,11 @@ public: SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); } + ObjCMethodFamily getMethodFamily() const { + if (HasMethod) return getMethodDecl()->getMethodFamily(); + return getSelector().getMethodFamily(); + } + /// \brief Return the number of actual arguments in this message, /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } @@ -808,7 +846,7 @@ public: }; /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. -/// (similiar in spirit to MemberExpr). +/// (similar in spirit to MemberExpr). class ObjCIsaExpr : public Expr { /// Base - the expression for the base object pointer. Stmt *Base; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 7b23766..6db2336 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the ExternalASTSource interface, which enables -// construction of AST nodes from some external source.x +// construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H @@ -16,7 +16,6 @@ #include "clang/AST/DeclBase.h" #include <cassert> -#include <vector> namespace llvm { template <class T> class SmallVectorImpl; @@ -26,9 +25,6 @@ namespace clang { class ASTConsumer; class CXXBaseSpecifier; -class Decl; -class DeclContext; -class DeclContextLookupResult; class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting class NamedDecl; @@ -74,17 +70,23 @@ public: /// /// This method only needs to be implemented if the AST source ever /// passes back decl sets as VisibleDeclaration objects. - virtual Decl *GetExternalDecl(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve a selector ID into a selector. /// /// This operation only needs to be implemented if the AST source /// returns non-zero for GetNumKnownSelectors(). - virtual Selector GetExternalSelector(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Selector GetExternalSelector(uint32_t ID); /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumExternalSelectors() = 0; + /// + /// The default implementation of this method is a no-op. + virtual uint32_t GetNumExternalSelectors(); /// \brief Resolve the offset of a statement in the decl stream into /// a statement. @@ -92,21 +94,26 @@ public: /// This operation is meant to be used via a LazyOffsetPtr. It only /// needs to be implemented if the AST source uses methods like /// FunctionDecl::setLazyBody when building decls. - virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0; - + /// + /// The default implementation of this method is a no-op. + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + /// \brief Finds all declarations with the given name in the /// given context. /// /// Generally the final step of this method is either to call /// SetExternalVisibleDeclsForName or to recursively call lookup on /// the DeclContext after calling SetExternalVisibleDecls. + /// + /// The default implementation of this method is a no-op. virtual DeclContextLookupResult - FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) = 0; + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); /// \brief Deserialize all the visible declarations from external storage. /// @@ -114,7 +121,9 @@ public: /// 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; + /// + /// The default implementation of this method is a no-op. + virtual void MaterializeVisibleDecls(const DeclContext *DC); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. @@ -124,9 +133,11 @@ public: /// are returned. /// /// \return true if an error occurred + /// + /// The default implementation of this method is a no-op. virtual bool FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Result) = 0; + llvm::SmallVectorImpl<Decl*> &Result); /// \brief Finds all declarations lexically contained within the given /// DeclContext. @@ -154,7 +165,7 @@ public: /// set on the ObjCInterfaceDecl via the function /// \c ObjCInterfaceDecl::setExternallyCompleted(). virtual void CompleteType(ObjCInterfaceDecl *Class) { } - + /// \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. @@ -179,6 +190,28 @@ public: /// /// The default implementation of this method is a no-op. virtual void PrintStats(); + + //===--------------------------------------------------------------------===// + // Queries for performance analysis. + //===--------------------------------------------------------------------===// + + struct MemoryBufferSizes { + size_t malloc_bytes; + size_t mmap_bytes; + + MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + }; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + MemoryBufferSizes getMemoryBufferSizes() const { + MemoryBufferSizes sizes(0, 0); + getMemoryBufferSizes(sizes); + return sizes; + } + + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const = 0; protected: static DeclContextLookupResult @@ -270,7 +303,7 @@ typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, &ExternalASTSource::GetExternalCXXBaseSpecifiers> LazyCXXBaseSpecifiersPtr; - + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 024bf40..c21c76b 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -312,6 +312,146 @@ public: } }; +/// \brief Class that aids in the construction of nested-name-specifiers along +/// with source-location information for all of the components of the +/// nested-name-specifier. +class NestedNameSpecifierLocBuilder { + /// \brief The current representation of the nested-name-specifier we're + /// building. + NestedNameSpecifier *Representation; + + /// \brief Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. + char *Buffer; + + /// \brief The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize; + + /// \brief The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity; + +public: + NestedNameSpecifierLocBuilder(); + + NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); + + NestedNameSpecifierLocBuilder & + operator=(const NestedNameSpecifierLocBuilder &Other); + + ~NestedNameSpecifierLocBuilder(); + + /// \brief Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier *getRepresentation() const { return Representation; } + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TemplateKWLoc The location of the 'template' keyword, if present. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, + SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'identifier::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Identifier The identifier. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + + /// \brief Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// \brief Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + SourceRange R); + + /// \brief Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// \brief Retrieve the source range covered by this nested-name-specifier. + SourceRange getSourceRange() const { + return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); + } + + /// \brief Retrieve a nested-name-specifier with location information, + /// copied into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; + + /// \brief Clear out this builder, and prepare it to build another + /// nested-name-specifier with source-location information. + void Clear() { + Representation = 0; + BufferSize = 0; + } + + /// \brief Retrieve the underlying buffer. + /// + /// \returns A pair containing a pointer to the buffer of source-location + /// data and the size of the source-location data that resides in that + /// buffer. + std::pair<char *, unsigned> getBuffer() const { + return std::make_pair(Buffer, BufferSize); + } +}; + /// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index a59c302..cf5fadb 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -38,7 +38,8 @@ struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), - SuppressTag(false), SuppressScope(false), + SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), + SuppressInitializers(false), Dump(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true) { } @@ -64,6 +65,16 @@ struct PrintingPolicy { /// "const int" type specifier and instead only print the "*y". bool SuppressSpecifiers : 1; + /// \brief Whether type printing should skip printing the tag keyword. + /// + /// This is used when printing the inner type of elaborated types, + /// (as the tag keyword is part of the elaborated type): + /// + /// \code + /// struct Geometry::Point; + /// \endcode + bool SuppressTagKeyword : 1; + /// \brief Whether type printing should skip printing the actual tag type. /// /// This is used when the caller needs to print a tag definition in front @@ -77,6 +88,19 @@ struct PrintingPolicy { /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; + /// \brief Suppress printing of variable initializers. + /// + /// This flag is used when printing the loop variable in a for-range + /// statement. For example, given: + /// + /// \code + /// for (auto x : coll) + /// \endcode + /// + /// SuppressInitializers will be true when printing "auto x", so that the + /// internal initializer constructed for x will not be printed. + bool SuppressInitializers : 1; + /// \brief True when we are "dumping" rather than "pretty-printing", /// where dumping involves printing the internal details of the AST /// and pretty-printing involves printing something similar to diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e85b6dc..930d193 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -600,12 +600,15 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( // FIXME: how can TSI ever be NULL? if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return true; + else + return getDerived().TraverseType(Arg.getAsType()); } case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (ArgLoc.getTemplateQualifierLoc()) + TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( + ArgLoc.getTemplateQualifierLoc())); return getDerived().TraverseTemplateName( Arg.getAsTemplateOrTemplatePattern()); @@ -933,7 +936,11 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { const FunctionProtoType *T = TL.getTypePtr(); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseDecl(TL.getArg(I))); + if (TL.getArg(I)) { + TRY_TO(TraverseDecl(TL.getArg(I))); + } else if (I < T->getNumArgs()) { + TRY_TO(TraverseType(T->getArgType(I))); + } } for (FunctionProtoType::exception_iterator E = T->exception_begin(), @@ -987,21 +994,22 @@ DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getTypePtr()->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); } TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); }) DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); } @@ -1041,7 +1049,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end(); Child != ChildEnd; ++Child) { - TRY_TO(TraverseDecl(*Child)); + // BlockDecls are traversed through BlockExprs. + if (!isa<BlockDecl>(*Child)) + TRY_TO(TraverseDecl(*Child)); } return true; @@ -1060,10 +1070,12 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled by the - // DEF_TRAVERSE_DECL macro already. + TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; }) DEF_TRAVERSE_DECL(FileScopeAsmDecl, { @@ -1164,9 +1176,17 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, { }) DEF_TRAVERSE_DECL(ObjCMethodDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled. - TRY_TO(TraverseStmt(D->getBody())); + if (D->getResultTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc())); + } + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); + } + return true; }) DEF_TRAVERSE_DECL(ObjCPropertyDecl, { @@ -1341,6 +1361,13 @@ DEF_TRAVERSE_DECL(TypedefDecl, { // source. }) +DEF_TRAVERSE_DECL(TypeAliasDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. + }) + DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template<class T> class A : public B<T> { using typename B<T>::foo; }; @@ -1354,7 +1381,7 @@ DEF_TRAVERSE_DECL(EnumDecl, { if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // The enumerators are already traversed by // decls_begin()/decls_end(). }) @@ -1367,7 +1394,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); return true; } @@ -1464,9 +1491,11 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); if (D->getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); return true; } @@ -1492,7 +1521,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // If we're an explicit template specialization, iterate over the // template args that were explicitly specified. If we were doing @@ -1678,13 +1707,14 @@ DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) +DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1692,7 +1722,7 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { }) DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); }) @@ -1707,10 +1737,9 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { }) DEF_TRAVERSE_STMT(MemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); - // FIXME: Should we be recursing on the qualifier? - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(ImplicitCastExpr, { @@ -1759,6 +1788,22 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { return true; } +// GenericSelectionExpr is a special case because the types and expressions +// are interleaved. We also need to watch out for null types (default +// generic associations). +template<typename Derived> +bool RecursiveASTVisitor<Derived>:: +TraverseGenericSelectionExpr(GenericSelectionExpr *S) { + TRY_TO(WalkUpFromGenericSelectionExpr(S)); + TRY_TO(TraverseStmt(S->getControllingExpr())); + for (unsigned i = 0; i != S->getNumAssocs(); ++i) { + if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) + TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); + TRY_TO(TraverseStmt(S->getAssocExpr(i))); + } + return true; +} + DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in // (i.e. non-class) type. @@ -1778,7 +1823,7 @@ DEF_TRAVERSE_STMT(OffsetOfExpr, { TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { +DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. if (S->isArgumentType()) @@ -1808,6 +1853,14 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(ExpressionTraitExpr, { + TRY_TO(TraverseStmt(S->getQueriedExpression())); + }) + DEF_TRAVERSE_STMT(VAArgExpr, { // The child-iterator will pick up the expression argument. TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); @@ -1834,7 +1887,10 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) DEF_TRAVERSE_STMT(AddrLabelExpr, { }) DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) -DEF_TRAVERSE_STMT(BlockExpr, { }) +DEF_TRAVERSE_STMT(BlockExpr, { + TRY_TO(TraverseDecl(S->getBlockDecl())); + return true; // no child statements to loop through. +}) DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) @@ -1869,7 +1925,7 @@ DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1877,13 +1933,17 @@ DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); } }) +DEF_TRAVERSE_STMT(SEHTryStmt, {}) +DEF_TRAVERSE_STMT(SEHExceptStmt, {}) +DEF_TRAVERSE_STMT(SEHFinallyStmt,{}) + DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) @@ -1921,7 +1981,7 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) // Candidates: // // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html // Every class that has getQualifier. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index d1f7d66..695fb04 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -158,6 +158,16 @@ protected: }; enum { NumExprBits = 15 }; + class DeclRefExprBitfields { + friend class DeclRefExpr; + friend class ASTStmtReader; // deserialization + unsigned : NumExprBits; + + unsigned HasQualifier : 1; + unsigned HasExplicitTemplateArgs : 1; + unsigned HasFoundDecl : 1; + }; + class CastExprBitfields { friend class CastExpr; unsigned : NumExprBits; @@ -180,6 +190,7 @@ protected: StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; ExprBitfields ExprBits; + DeclRefExprBitfields DeclRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; }; @@ -383,14 +394,15 @@ public: class NullStmt : public Stmt { SourceLocation SemiLoc; - /// \brief Whether the null statement was preceded by an empty macro, e.g: + /// \brief If the null statement was preceded by an empty macro this is + /// its instantiation source location, e.g: /// @code /// #define CALL(x) /// CALL(0); /// @endcode - bool LeadingEmptyMacro; + SourceLocation LeadingEmptyMacro; public: - NullStmt(SourceLocation L, bool LeadingEmptyMacro = false) + NullStmt(SourceLocation L, SourceLocation LeadingEmptyMacro =SourceLocation()) : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {} /// \brief Build an empty null statement. @@ -399,7 +411,8 @@ public: SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } - bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; } + bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro.isValid(); } + SourceLocation getLeadingEmptyMacroLoc() const { return LeadingEmptyMacro; } SourceRange getSourceRange() const { return SourceRange(SemiLoc); } @@ -424,6 +437,8 @@ public: SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { CompoundStmtBits.NumStmts = NumStmts; + assert(CompoundStmtBits.NumStmts == NumStmts && + "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); if (NumStmts == 0) { Body = 0; @@ -516,6 +531,9 @@ public: void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } Stmt *getSubStmt(); + const Stmt *getSubStmt() const { + return const_cast<SwitchCase*>(this)->getSubStmt(); + } SourceRange getSourceRange() const { return SourceRange(); } @@ -527,7 +545,7 @@ public: }; class CaseStmt : public SwitchCase { - enum { SUBSTMT, LHS, RHS, END_EXPR }; + enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension SourceLocation CaseLoc; @@ -688,6 +706,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this IfStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -754,6 +778,12 @@ public: /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + + /// If this SwitchStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } @@ -835,6 +865,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this WhileStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } @@ -939,6 +975,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this ForStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]); + } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } @@ -1406,6 +1448,122 @@ public: } }; +class SEHExceptStmt : public Stmt { + SourceLocation Loc; + Stmt *Children[2]; + + enum { FILTER_EXPR, BLOCK }; + + SEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block); + +public: + static SEHExceptStmt* Create(ASTContext &C, + SourceLocation ExceptLoc, + Expr *FilterExpr, + Stmt *Block); + SourceRange getSourceRange() const { + return SourceRange(getExceptLoc(), getEndLoc()); + } + + SourceLocation getExceptLoc() const { return Loc; } + SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } + + Expr *getFilterExpr() const { return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); } + CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Children[BLOCK]); } + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHExceptStmtClass; + } + + static bool classof(SEHExceptStmt *) { return true; } + +}; + +class SEHFinallyStmt : public Stmt { + SourceLocation Loc; + Stmt *Block; + + SEHFinallyStmt(SourceLocation Loc, + Stmt *Block); + +public: + static SEHFinallyStmt* Create(ASTContext &C, + SourceLocation FinallyLoc, + Stmt *Block); + + SourceRange getSourceRange() const { + return SourceRange(getFinallyLoc(), getEndLoc()); + } + + SourceLocation getFinallyLoc() const { return Loc; } + SourceLocation getEndLoc() const { return Block->getLocEnd(); } + + CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Block); } + + child_range children() { + return child_range(&Block,&Block+1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHFinallyStmtClass; + } + + static bool classof(SEHFinallyStmt *) { return true; } + +}; + +class SEHTryStmt : public Stmt { + bool IsCXXTry; + SourceLocation TryLoc; + Stmt *Children[2]; + + enum { TRY = 0, HANDLER = 1 }; + + SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + +public: + static SEHTryStmt* Create(ASTContext &C, + bool isCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + + SourceRange getSourceRange() const { + return SourceRange(getTryLoc(), getEndLoc()); + } + + SourceLocation getTryLoc() const { return TryLoc; } + SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } + + bool getIsCXXTry() const { return IsCXXTry; } + CompoundStmt* getTryBlock() const { return llvm::cast<CompoundStmt>(Children[TRY]); } + Stmt *getHandler() const { return Children[HANDLER]; } + + /// Returns 0 if not defined + SEHExceptStmt *getExceptHandler() const; + SEHFinallyStmt *getFinallyHandler() const; + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHTryStmtClass; + } + + static bool classof(SEHTryStmt *) { return true; } + +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index f08815f..42dcf2b 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -119,6 +119,88 @@ public: friend class ASTStmtReader; }; +/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for +/// statement, represented as 'for (range-declarator : range-expression)'. +/// +/// This is stored in a partially-desugared form to allow full semantic +/// analysis of the constituent components. The original syntactic components +/// can be extracted using getLoopVariable and getRangeInit. +class CXXForRangeStmt : public Stmt { + enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; + // SubExprs[RANGE] is an expression or declstmt. + // SubExprs[COND] and SubExprs[INC] are expressions. + Stmt *SubExprs[END]; + SourceLocation ForLoc; + SourceLocation ColonLoc; + SourceLocation RParenLoc; +public: + CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, + Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, + SourceLocation FL, SourceLocation CL, SourceLocation RPL); + CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } + + + VarDecl *getLoopVariable(); + Expr *getRangeInit(); + + const VarDecl *getLoopVariable() const; + const Expr *getRangeInit() const; + + + DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } + DeclStmt *getBeginEndStmt() { return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); } + Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } + Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } + DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } + Stmt *getBody() { return SubExprs[BODY]; } + + const DeclStmt *getRangeStmt() const { + return cast<DeclStmt>(SubExprs[RANGE]); + } + const DeclStmt *getBeginEndStmt() const { + return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); + } + const Expr *getCond() const { + return cast_or_null<Expr>(SubExprs[COND]); + } + const Expr *getInc() const { + return cast_or_null<Expr>(SubExprs[INC]); + } + const DeclStmt *getLoopVarStmt() const { + return cast<DeclStmt>(SubExprs[LOOPVAR]); + } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } + void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } + void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } + void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation Loc) { ForLoc = Loc; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } + + SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXForRangeStmtClass; + } + static bool classof(const CXXForRangeStmt *) { return true; } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END]); + } +}; + } // end namespace clang diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 851c001..05b50db 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -18,6 +18,7 @@ #include <cassert> #include <cstddef> #include <iterator> +#include <utility> namespace clang { diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index a4e074e..821b4fc 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -362,7 +362,10 @@ private: Expr *Expression; TypeSourceInfo *Declarator; struct { - unsigned QualifierRange[2]; + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; unsigned TemplateNameLoc; unsigned EllipsisLoc; } Template; @@ -375,12 +378,12 @@ public: TemplateArgumentLocInfo(Expr *E) : Expression(E) {} - TemplateArgumentLocInfo(SourceRange QualifierRange, + TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { - Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); - Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template.QualifierLocData = QualifierLoc.getOpaqueData(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); } @@ -393,10 +396,9 @@ public: return Expression; } - SourceRange getTemplateQualifierRange() const { - return SourceRange( - SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), - SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + NestedNameSpecifierLoc getTemplateQualifierLoc() const { + return NestedNameSpecifierLoc(Template.Qualifier, + Template.QualifierLocData); } SourceLocation getTemplateNameLoc() const { @@ -433,11 +435,10 @@ public: } TemplateArgumentLoc(const TemplateArgument &Argument, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), - LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { + : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } @@ -477,10 +478,10 @@ public: return LocInfo.getAsExpr(); } - SourceRange getTemplateQualifierRange() const { + NestedNameSpecifierLoc getTemplateQualifierLoc() const { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateQualifierRange(); + return LocInfo.getTemplateQualifierLoc(); } SourceLocation getTemplateNameLoc() const { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 9b177cc..975a66f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TYPE_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" @@ -72,7 +73,7 @@ namespace llvm { namespace clang { class ASTContext; - class TypedefDecl; + class TypedefNameDecl; class TemplateDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; @@ -212,6 +213,11 @@ public: assert(type); setObjCGCAttr(type); } + Qualifiers withoutObjCGCAttr() const { + Qualifiers qs = *this; + qs.removeObjCGCAttr(); + return qs; + } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } @@ -293,8 +299,10 @@ public: (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } - bool isSupersetOf(Qualifiers Other) const; - + /// \brief Determine whether this set of qualifiers is a strict superset of + /// another set of qualifiers, not considering qualifier compatibility. + bool isStrictSupersetOf(Qualifiers Other) const; + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } @@ -354,7 +362,9 @@ enum CallingConv { CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86Pascal // __attribute__((pascal)) + CC_X86Pascal, // __attribute__((pascal)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP // __attribute__((pcs("aapcs-vfp"))) }; typedef std::pair<const Type*, Qualifiers> SplitQualType; @@ -598,8 +608,14 @@ public: /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; + /// \brief Determine whether this type is more qualified than the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; + + /// \brief Determine whether this type is at least as qualified as the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; + QualType getNonReferenceType() const; /// \brief Determine the type of a (typically non-lvalue) expression with the @@ -1163,6 +1179,20 @@ public: /// (C++0x [basic.types]p10) bool isLiteralType() const; + /// isTrivialType - Return true if this is a trivial type + /// (C++0x [basic.types]p9) + bool isTrivialType() const; + + /// \brief Test if this type is a standard-layout type. + /// (C++0x [basic.type]p9) + bool isStandardLayoutType() const; + + /// isCXX11PODType() - Return true if this is a POD type according to the + /// more relaxed rules of the C++11 standard, regardless of the current + /// compilation's language. + /// (C++0x [basic.types]p9) + bool isCXX11PODType() const; + /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. @@ -1178,6 +1208,9 @@ public: /// BuiltinTypes. bool isPlaceholderType() const; + /// isSpecificPlaceholderType - Test for a specific placeholder type. + bool isSpecificPlaceholderType(unsigned K) const; + /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) @@ -1207,6 +1240,8 @@ public: bool isDerivedType() const; // C99 6.2.5p20 bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; + bool isFundamentalType() const; + bool isCompoundType() const; // Type Predicates: Check to see if this type is structurally the specified // type, ignoring typedefs and qualifiers. @@ -1321,6 +1356,7 @@ public: // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; + const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; @@ -1475,25 +1511,52 @@ public: NullPtr, // This is the type of C++0x 'nullptr'. + /// The primitive Objective C 'id' type. The user-visible 'id' + /// type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The user-visible + /// 'Class' type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCClass, + + /// The primitive Objective C 'SEL' type. The user-visible 'SEL' + /// type is a typedef of a PointerType to this. + ObjCSel, + /// This represents the type of an expression whose type is /// totally unknown, e.g. 'T::foo'. It is permitted for this to /// appear in situations where the structure of the type is /// theoretically deducible. Dependent, - Overload, // This represents the type of an overloaded function declaration. - - /// The primitive Objective C 'id' type. The type pointed to by the - /// user-visible 'id' type. Only ever shows up in an AST as the base - /// type of an ObjCObjectType. - ObjCId, - - /// The primitive Objective C 'Class' type. The type pointed to by the - /// user-visible 'Class' type. Only ever shows up in an AST as the - /// base type of an ObjCObjectType. - ObjCClass, - - ObjCSel // This represents the ObjC 'SEL' type. + /// The type of an unresolved overload set. A placeholder type. + /// Expressions with this type have one of the following basic + /// forms, with parentheses generally permitted: + /// foo # possibly qualified, not if an implicit access + /// foo # possibly qualified, not if an implicit access + /// &foo # possibly qualified, not if an implicit access + /// x->foo # only if might be a static member function + /// &x->foo # only if might be a static member function + /// &Class::foo # when a pointer-to-member; sub-expr also has this type + /// OverloadExpr::find can be used to analyze the expression. + Overload, + + /// The type of a bound C++ non-static member function. + /// A placeholder type. Expressions with this type have one of the + /// following basic forms: + /// foo # if an implicit access + /// x->foo # if only contains non-static members + BoundMember, + + /// __builtin_any_type. A placeholder type. Useful for clients + /// like debuggers that don't know what type to give something. + /// Only a small number of operations are valid on expressions of + /// unknown type, most notably explicit casts. + UnknownAny }; public: @@ -1526,11 +1589,11 @@ public: return getKind() >= Float && getKind() <= LongDouble; } - /// Determines whether this type is a "forbidden" placeholder type, - /// i.e. a type which cannot appear in arbitrary positions in a - /// fully-formed expression. + /// Determines whether this type is a placeholder type, i.e. a type + /// which cannot appear in arbitrary positions in a fully-formed + /// expression. bool isPlaceholderType() const { - return getKind() == Overload; + return getKind() >= Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -1991,7 +2054,7 @@ public: friend class StmtIteratorBase; void Profile(llvm::FoldingSetNodeID &ID) { - assert(0 && "Cannnot unique VariableArrayTypes."); + assert(0 && "Cannot unique VariableArrayTypes."); } }; @@ -2257,12 +2320,13 @@ class FunctionType : public Type { // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|regparm - // |0 .. 2| 3 |4 .. 6 + // | CC |noreturn|hasregparm|regparm + // |0 .. 2| 3 | 4 |5 .. 7 enum { CallConvMask = 0x7 }; enum { NoReturnMask = 0x8 }; + enum { HasRegParmMask = 0x10 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask), - RegParmOffset = 4 }; + RegParmOffset = 5 }; unsigned char Bits; @@ -2273,9 +2337,10 @@ class FunctionType : public Type { public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) { + ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) { Bits = ((unsigned) cc) | (noReturn ? NoReturnMask : 0) | + (hasRegParm ? HasRegParmMask : 0) | (regParm << RegParmOffset); } @@ -2284,6 +2349,7 @@ class FunctionType : public Type { ExtInfo() : Bits(0) {} bool getNoReturn() const { return Bits & NoReturnMask; } + bool getHasRegParm() const { return Bits & HasRegParmMask; } unsigned getRegParm() const { return Bits >> RegParmOffset; } CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } @@ -2305,7 +2371,7 @@ class FunctionType : public Type { } ExtInfo withRegParm(unsigned RegParm) const { - return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset)); + return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset)); } ExtInfo withCallingConv(CallingConv cc) const { @@ -2341,7 +2407,8 @@ protected: public: QualType getResultType() const { return ResultType; } - + + bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } @@ -2403,17 +2470,17 @@ public: /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : - Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false), - TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {} + Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0), + RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0) {} FunctionType::ExtInfo ExtInfo; bool Variadic; - bool HasExceptionSpec; - bool HasAnyExceptionSpec; + ExceptionSpecificationType ExceptionSpecType; unsigned char TypeQuals; RefQualifierKind RefQualifier; unsigned NumExceptions; const QualType *Exceptions; + Expr *NoexceptExpr; }; private: @@ -2435,13 +2502,10 @@ private: unsigned NumArgs : 20; /// NumExceptions - The number of types in the exception spec, if any. - unsigned NumExceptions : 10; + unsigned NumExceptions : 9; - /// HasExceptionSpec - Whether this function has an exception spec at all. - unsigned HasExceptionSpec : 1; - - /// HasAnyExceptionSpec - Whether this function has a throw(...) spec. - unsigned HasAnyExceptionSpec : 1; + /// ExceptionSpecType - The type of exception specification this function has. + unsigned ExceptionSpecType : 3; /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2449,6 +2513,9 @@ private: /// Exceptions - There is another variable size array after ArgInfo that /// holds the exception types. + /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing + /// to the expression in the noexcept() specifier. + friend class ASTContext; // ASTContext creates these. public: @@ -2462,29 +2529,66 @@ public: ExtProtoInfo EPI; EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); - EPI.HasExceptionSpec = hasExceptionSpec(); - EPI.HasAnyExceptionSpec = hasAnyExceptionSpec(); + EPI.ExceptionSpecType = getExceptionSpecType(); EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = NumExceptions; + EPI.Exceptions = exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + EPI.NoexceptExpr = getNoexceptExpr(); + } return EPI; } - bool hasExceptionSpec() const { return HasExceptionSpec; } - bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; } + /// \brief Get the kind of exception specification on this function. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast<ExceptionSpecificationType>(ExceptionSpecType); + } + /// \brief Return whether this function has any kind of exception spec. + bool hasExceptionSpec() const { + return getExceptionSpecType() != EST_None; + } + /// \brief Return whether this function has a dynamic (throw) exception spec. + bool hasDynamicExceptionSpec() const { + return isDynamicExceptionSpec(getExceptionSpecType()); + } + /// \brief Return whether this function has a noexcept exception spec. + bool hasNoexceptExceptionSpec() const { + return isNoexceptExceptionSpec(getExceptionSpecType()); + } + /// \brief Result type of getNoexceptSpec(). + enum NoexceptResult { + NR_NoNoexcept, ///< There is no noexcept specifier. + NR_BadNoexcept, ///< The noexcept specifier has a bad expression. + NR_Dependent, ///< The noexcept specifier is dependent. + NR_Throw, ///< The noexcept specifier evaluates to false. + NR_Nothrow ///< The noexcept specifier evaluates to true. + }; + /// \brief Get the meaning of the noexcept spec on this function, if any. + NoexceptResult getNoexceptSpec(ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); return exception_begin()[i]; } - bool hasEmptyExceptionSpec() const { - return hasExceptionSpec() && !hasAnyExceptionSpec() && - getNumExceptions() == 0; + Expr *getNoexceptExpr() const { + if (getExceptionSpecType() != EST_ComputedNoexcept) + return 0; + // NoexceptExpr sits where the arguments end. + return *reinterpret_cast<Expr *const *>(arg_type_end()); + } + bool isNothrow(ASTContext &Ctx) const { + ExceptionSpecificationType EST = getExceptionSpecType(); + if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) + return true; + if (EST != EST_ComputedNoexcept) + return false; + return getNoexceptSpec(Ctx) == NR_Nothrow; } using FunctionType::isVariadic; - + /// \brief Determines whether this function prototype contains a /// parameter pack at the end. /// @@ -2513,6 +2617,8 @@ public: return arg_type_end(); } exception_iterator exception_end() const { + if (getExceptionSpecType() != EST_Dynamic) + return exception_begin(); return exception_begin() + NumExceptions; } @@ -2524,10 +2630,10 @@ public: } static bool classof(const FunctionProtoType *) { return true; } - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, arg_type_iterator ArgTys, unsigned NumArgs, - const ExtProtoInfo &EPI); + const ExtProtoInfo &EPI, const ASTContext &Context); }; @@ -2566,18 +2672,18 @@ public: class TypedefType : public Type { - TypedefDecl *Decl; + TypedefNameDecl *Decl; protected: - TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefDecl*>(D)) { + Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. public: - TypedefDecl *getDecl() const { return Decl; } + TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } QualType desugar() const; @@ -2807,9 +2913,10 @@ public: // Enumerated operand (string or keyword). attr_objc_gc, + attr_pcs, FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_objc_gc, + LastEnumOperandKind = attr_pcs, // No operand. attr_noreturn, @@ -2864,44 +2971,68 @@ public: }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { - unsigned Depth : 15; - unsigned ParameterPack : 1; - unsigned Index : 16; - IdentifierInfo *Name; + // Helper data collector for canonical types. + struct CanonicalTTPTInfo { + unsigned Depth : 15; + unsigned ParameterPack : 1; + unsigned Index : 16; + }; + + union { + // Info for the canonical type. + CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; + }; - TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, - QualType Canon) + /// Build a non-canonical type. + TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(N) { } + /*VariablyModified=*/false, + Canon->containsUnexpandedParameterPack()), + TTPDecl(TTPDecl) { } + /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(0) { } + /*VariablyModified=*/false, PP) { + CanTTPTInfo.Depth = D; + CanTTPTInfo.Index = I; + CanTTPTInfo.ParameterPack = PP; + } friend class ASTContext; // ASTContext creates these + const CanonicalTTPTInfo& getCanTTPTInfo() const { + QualType Can = getCanonicalTypeInternal(); + return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo; + } + public: - unsigned getDepth() const { return Depth; } - unsigned getIndex() const { return Index; } - bool isParameterPack() const { return ParameterPack; } - IdentifierInfo *getName() const { return Name; } + unsigned getDepth() const { return getCanTTPTInfo().Depth; } + unsigned getIndex() const { return getCanTTPTInfo().Index; } + bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } + + TemplateTypeParmDecl *getDecl() const { + return isCanonicalUnqualified() ? 0 : TTPDecl; + } + + IdentifierInfo *getIdentifier() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Depth, Index, ParameterPack, Name); + Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) { + TemplateTypeParmDecl *TTPDecl) { ID.AddInteger(Depth); ID.AddInteger(Index); ID.AddBoolean(ParameterPack); - ID.AddPointer(Name); + ID.AddPointer(TTPDecl); } static bool classof(const Type *T) { @@ -2930,8 +3061,6 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } - /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { return Replaced; @@ -2992,7 +3121,7 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } + IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { @@ -4064,12 +4193,6 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { return getFunctionExtInfo(*t); } -/// \brief Determine whether this set of qualifiers is a superset of the given -/// set of qualifiers. -inline bool Qualifiers::isSupersetOf(Qualifiers Other) const { - return Mask != Other.Mask && (Mask | Other.Mask) == Mask; -} - /// isMoreQualifiedThan - Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and @@ -4105,6 +4228,40 @@ inline QualType QualType::getNonReferenceType() const { return *this; } +/// \brief Tests whether the type is categorized as a fundamental type. +/// +/// \returns True for types specified in C++0x [basic.fundamental]. +inline bool Type::isFundamentalType() const { + return isVoidType() || + // FIXME: It's really annoying that we don't have an + // 'isArithmeticType()' which agrees with the standard definition. + (isArithmeticType() && !isEnumeralType()); +} + +/// \brief Tests whether the type is categorized as a compound type. +/// +/// \returns True for types specified in C++0x [basic.compound]. +inline bool Type::isCompoundType() const { + // C++0x [basic.compound]p1: + // Compound types can be constructed in the following ways: + // -- arrays of objects of a given type [...]; + return isArrayType() || + // -- functions, which have parameters of given types [...]; + isFunctionType() || + // -- pointers to void or objects or functions [...]; + isPointerType() || + // -- references to objects or functions of a given type. [...] + isReferenceType() || + // -- classes containing a sequence of objects of various types, [...]; + isRecordType() || + // -- unions, which ar classes capable of containing objects of different types at different times; + isUnionType() || + // -- enumerations, which comprise a set of named constant values. [...]; + isEnumeralType() || + // -- pointers to non-static class members, [...]. + isMemberPointerType(); +} + inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } @@ -4236,6 +4393,12 @@ inline bool Type::isPlaceholderType() const { return false; } +inline bool Type::isSpecificPlaceholderType(unsigned K) const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + return (BT->getKind() == (BuiltinType::Kind) K); + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index c7f5ee7..a1df744 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -527,7 +527,7 @@ class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, TypedefType> { public: - TypedefDecl *getTypedefDecl() const { + TypedefNameDecl *getTypedefNameDecl() const { return getTypePtr()->getDecl(); } }; @@ -584,6 +584,8 @@ class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TemplateTypeParmTypeLoc, TemplateTypeParmType> { +public: + TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for substituted template type parameters. @@ -943,10 +945,14 @@ public: } }; +struct MemberPointerLocInfo : public PointerLikeLocInfo { + TypeSourceInfo *ClassTInfo; +}; /// \brief Wrapper for source info for member pointers. class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, - MemberPointerType> { + MemberPointerType, + MemberPointerLocInfo> { public: SourceLocation getStarLoc() const { return getSigilLoc(); @@ -954,6 +960,28 @@ public: void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } + + const Type *getClass() const { + return getTypePtr()->getClass(); + } + TypeSourceInfo *getClassTInfo() const { + return getLocalData()->ClassTInfo; + } + void setClassTInfo(TypeSourceInfo* TI) { + getLocalData()->ClassTInfo = TI; + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setSigilLoc(Loc); + setClassTInfo(0); + } + + SourceRange getLocalSourceRange() const { + if (TypeSourceInfo *TI = getClassTInfo()) + return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); + else + return SourceRange(getStarLoc()); + } }; /// Wraps an ObjCPointerType with source location information. @@ -1007,7 +1035,8 @@ public: struct FunctionLocInfo { - SourceLocation LParenLoc, RParenLoc; + SourceLocation LocalRangeBegin; + SourceLocation LocalRangeEnd; bool TrailingReturn; }; @@ -1017,18 +1046,18 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionType, FunctionLocInfo> { public: - SourceLocation getLParenLoc() const { - return getLocalData()->LParenLoc; + SourceLocation getLocalRangeBegin() const { + return getLocalData()->LocalRangeBegin; } - void setLParenLoc(SourceLocation Loc) { - getLocalData()->LParenLoc = Loc; + void setLocalRangeBegin(SourceLocation L) { + getLocalData()->LocalRangeBegin = L; } - SourceLocation getRParenLoc() const { - return getLocalData()->RParenLoc; + SourceLocation getLocalRangeEnd() const { + return getLocalData()->LocalRangeEnd; } - void setRParenLoc(SourceLocation Loc) { - getLocalData()->RParenLoc = Loc; + void setLocalRangeEnd(SourceLocation L) { + getLocalData()->LocalRangeEnd = L; } bool getTrailingReturn() const { @@ -1056,12 +1085,12 @@ public: } SourceRange getLocalSourceRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); + return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setLParenLoc(Loc); - setRParenLoc(Loc); + setLocalRangeBegin(Loc); + setLocalRangeEnd(Loc); setTrailingReturn(false); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); @@ -1388,7 +1417,10 @@ class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, struct ElaboratedLocInfo { SourceLocation KeywordLoc; - SourceRange QualifierRange; + + /// \brief Opaque data pointer used to reconstruct a nested-name-specifier + /// from + void *QualifierData; }; class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, @@ -1403,27 +1435,29 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) - if (getQualifierRange().getEnd().isValid()) - return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + if (getQualifierLoc()) + return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc()); else return SourceRange(getKeywordLoc()); else - return getQualifierRange(); + return getQualifierLoc().getSourceRange(); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); @@ -1444,6 +1478,9 @@ public: // type is some sort of TypeDeclTypeLoc. struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; + + /// \brief Data associated with the nested-name-specifier location. + void *QualifierData; }; class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, @@ -1458,13 +1495,18 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } - + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -1476,7 +1518,7 @@ public: if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getNameLoc()); else - return SourceRange(getQualifierRange().getBegin(), getNameLoc()); + return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); } void copy(DependentNameTypeLoc Loc) { @@ -1485,16 +1527,11 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); }; -// This is exactly the structure of an ElaboratedTypeLoc whose inner -// type is some sort of TemplateSpecializationTypeLoc. struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { + SourceLocation KeywordLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // followed by a TemplateArgumentLocInfo[] @@ -1513,11 +1550,28 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; - } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + NestedNameSpecifierLoc getQualifierLoc() const { + if (!getLocalData()->QualifierData) + return NestedNameSpecifierLoc(); + + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); + } + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) { + // Even if we have a nested-name-specifier in the dependent + // template specialization type, we won't record the nested-name-specifier + // location information when this type-source location information is + // part of a nested-name-specifier. + getLocalData()->QualifierData = 0; + return; + } + + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getNameLoc() const { @@ -1559,8 +1613,10 @@ public: SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getRAngleLoc()); + else if (getQualifierLoc()) + return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); else - return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + return SourceRange(getNameLoc(), getRAngleLoc()); } void copy(DependentTemplateSpecializationTypeLoc Loc) { @@ -1569,16 +1625,7 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - setLAngleLoc(Loc); - setRAngleLoc(Loc); - TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), - getTypePtr()->getArgs(), - getArgInfos(), Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); |