diff options
Diffstat (limited to 'include/clang/AST')
| -rw-r--r-- | include/clang/AST/ASTContext.h | 27 | ||||
| -rw-r--r-- | include/clang/AST/Attr.h | 2 | ||||
| -rw-r--r-- | include/clang/AST/CanonicalType.h | 17 | ||||
| -rw-r--r-- | include/clang/AST/Decl.h | 10 | ||||
| -rw-r--r-- | include/clang/AST/DeclBase.h | 11 | ||||
| -rw-r--r-- | include/clang/AST/DeclCXX.h | 364 | ||||
| -rw-r--r-- | include/clang/AST/DeclContextInternals.h | 3 | ||||
| -rw-r--r-- | include/clang/AST/DeclNodes.def | 4 | ||||
| -rw-r--r-- | include/clang/AST/DeclObjC.h | 32 | ||||
| -rw-r--r-- | include/clang/AST/DeclTemplate.h | 17 | ||||
| -rw-r--r-- | include/clang/AST/DeclarationName.h | 3 | ||||
| -rw-r--r-- | include/clang/AST/Expr.h | 11 | ||||
| -rw-r--r-- | include/clang/AST/ExprCXX.h | 2 | ||||
| -rw-r--r-- | include/clang/AST/RecordLayout.h | 2 | ||||
| -rw-r--r-- | include/clang/AST/Redeclarable.h | 3 | ||||
| -rw-r--r-- | include/clang/AST/TemplateBase.h | 100 | ||||
| -rw-r--r-- | include/clang/AST/Type.h | 315 | ||||
| -rw-r--r-- | include/clang/AST/TypeLoc.h | 12 | ||||
| -rw-r--r-- | include/clang/AST/TypeLocBuilder.h | 1 |
19 files changed, 557 insertions, 379 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7392170be995c..f9d2f71b1f289 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -37,6 +37,7 @@ namespace llvm { namespace clang { class FileManager; class ASTRecordLayout; + class BlockExpr; class Expr; class ExternalASTSource; class IdentifierTable; @@ -55,7 +56,6 @@ namespace clang { class TranslationUnitDecl; class TypeDecl; class TypedefDecl; - class UnresolvedUsingDecl; class UsingDecl; namespace Builtin { class Context; } @@ -204,7 +204,7 @@ class ASTContext { /// /// This mapping will contain an entry that maps from the UsingDecl in /// B<int> to the UnresolvedUsingDecl in B<T>. - llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *> + llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUnresolvedUsingDecl; llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; @@ -232,7 +232,7 @@ class ASTContext { llvm::DenseMap<const Decl *, std::string> DeclComments; public: - TargetInfo &Target; + const TargetInfo &Target; IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; @@ -284,12 +284,11 @@ public: /// \brief If this using decl is instantiated from an unresolved using decl, /// return it. - UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); /// \brief Note that the using decl \p Inst is an instantiation of /// the unresolved using decl \p Tmpl of a class template. - void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, - UnresolvedUsingDecl *Tmpl); + void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl); FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); @@ -319,7 +318,7 @@ public: CanQualType UndeducedAutoTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; - ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, bool FreeMemory = true, unsigned size_reserve=0); @@ -672,6 +671,10 @@ public: /// declaration. void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); + /// getObjCEncodingForBlockDecl - Return the encoded type for this block + /// declaration. + void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S); + /// getObjCEncodingForPropertyDecl - Return the encoded type for /// this method declaration. If non-NULL, Container must be either /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should @@ -872,9 +875,9 @@ public: /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) { - T1 = getCanonicalType(T1); - T2 = getCanonicalType(T2); - return T1.getUnqualifiedType() == T2.getUnqualifiedType(); + CanQualType CT1 = getCanonicalType(T1); + CanQualType CT2 = getCanonicalType(T2); + return CT1.getUnqualifiedType() == CT2.getUnqualifiedType(); } /// \brief Retrieves the "canonical" declaration of @@ -925,6 +928,10 @@ public: /// types, values, and templates. TemplateName getCanonicalTemplateName(TemplateName Name); + /// \brief Determine whether the given template names refer to the same + /// template. + bool hasSameTemplateName(TemplateName X, TemplateName Y); + /// \brief Retrieve the "canonical" template argument. /// /// The canonical template argument is the simplest template argument diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index f7a47364a7f61..b36ff1229376c 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -50,6 +50,7 @@ public: Annotate, AsmLabel, // Represent GCC asm label extension. Blocks, + CDecl, Cleanup, Const, Constructor, @@ -442,6 +443,7 @@ DEF_SIMPLE_ATTR(DLLImport); DEF_SIMPLE_ATTR(DLLExport); DEF_SIMPLE_ATTR(FastCall); DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(CDecl); DEF_SIMPLE_ATTR(TransparentUnion); DEF_SIMPLE_ATTR(ObjCNSObject); DEF_SIMPLE_ATTR(ObjCException); diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index a7750517090e6..9b1187770f6ac 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -71,6 +71,9 @@ public: /// \brief Implicit conversion to a qualified type. operator QualType() const { return Stored; } + /// \brief Implicit conversion to bool. + operator bool() const { return !isNull(); } + bool isNull() const { return Stored.isNull(); } @@ -99,22 +102,22 @@ public: CanProxy<T> operator->() const; /// \brief Retrieve all qualifiers. - Qualifiers getQualifiers() const { return Stored.getQualifiers(); } + Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } /// \brief Retrieve the const/volatile/restrict qualifiers. - unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); } + unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } /// \brief Determines whether this type has any qualifiers - bool hasQualifiers() const { return Stored.hasQualifiers(); } + bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } bool isConstQualified() const { - return Stored.isConstQualified(); + return Stored.isLocalConstQualified(); } bool isVolatileQualified() const { - return Stored.isVolatileQualified(); + return Stored.isLocalVolatileQualified(); } bool isRestrictQualified() const { - return Stored.isRestrictQualified(); + return Stored.isLocalRestrictQualified(); } /// \brief Retrieve the unqualified form of this type. @@ -635,7 +638,7 @@ struct CanProxyAdaptor<ObjCObjectPointerType> //----------------------------------------------------------------------------// template<typename T> inline CanQual<T> CanQual<T>::getUnqualifiedType() const { - return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType()); + return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); } template<typename T> diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 813e83accdb1a..ac79a91792d71 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -232,6 +232,7 @@ public: void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } + const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), RBracLoc); @@ -552,6 +553,9 @@ public: } virtual VarDecl *getCanonicalDecl(); + const VarDecl *getCanonicalDecl() const { + return const_cast<VarDecl*>(this)->getCanonicalDecl(); + } /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. @@ -1424,6 +1428,9 @@ public: virtual SourceRange getSourceRange() const; virtual TagDecl* getCanonicalDecl(); + const TagDecl* getCanonicalDecl() const { + return const_cast<TagDecl*>(this)->getCanonicalDecl(); + } /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { @@ -1515,6 +1522,9 @@ public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } + const EnumDecl *getCanonicalDecl() const { + return cast<EnumDecl>(TagDecl::getCanonicalDecl()); + } static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 10db7030db18e..79f7663561383 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -79,9 +79,11 @@ public: /// namespaces, labels, tags, members and ordinary /// identifiers. These are meant as bitmasks, so that searches in /// C++ can look into the "tag" namespace during ordinary lookup. We - /// use additional namespaces for Objective-C entities. We also - /// put C++ friend declarations (of previously-undeclared entities) in - /// shadow namespaces. + /// use additional namespaces for Objective-C entities. We also put + /// C++ friend declarations (of previously-undeclared entities) in + /// shadow namespaces, and 'using' declarations (as opposed to their + /// implicit shadow declarations) can be found in their own + /// namespace. enum IdentifierNamespace { IDNS_Label = 0x1, IDNS_Tag = 0x2, @@ -91,7 +93,8 @@ public: IDNS_ObjCImplementation = 0x20, IDNS_ObjCCategoryImpl = 0x40, IDNS_OrdinaryFriend = 0x80, - IDNS_TagFriend = 0x100 + IDNS_TagFriend = 0x100, + IDNS_Using = 0x200 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index c858c5c0df787..e5bf78cd10d25 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -432,6 +432,9 @@ public: virtual CXXRecordDecl *getCanonicalDecl() { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } + virtual const CXXRecordDecl *getCanonicalDecl() const { + return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); + } static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -768,7 +771,7 @@ public: /// \param Base the base class we are searching for. /// /// \returns true if this class is derived from Base, false otherwise. - bool isDerivedFrom(CXXRecordDecl *Base); + bool isDerivedFrom(CXXRecordDecl *Base) const; /// \brief Determine whether this class is derived from the type \p Base. /// @@ -786,7 +789,7 @@ public: /// /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths - bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths); + bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; /// \brief Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. @@ -801,7 +804,7 @@ public: /// lookupInBases(). /// /// \returns true if this base matched the search criteria, false otherwise. - typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier, + typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); @@ -826,7 +829,7 @@ public: /// \returns true if there exists any path from this class to a base class /// subobject that matches the search criteria. bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, - CXXBasePaths &Paths); + CXXBasePaths &Paths) const; /// \brief Base-class lookup callback that determines whether the given /// base class specifier refers to a specific class declaration. @@ -835,8 +838,8 @@ public: /// a given derived class has is a base class subobject of a particular type. /// The user data pointer should refer to the canonical CXXRecordDecl of the /// base class that we are searching for. - static bool FindBaseClass(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *BaseRecord); + static bool FindBaseClass(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *BaseRecord); /// \brief Base-class lookup callback that determines whether there exists /// a tag with the given name. @@ -844,8 +847,8 @@ public: /// This callback can be used with \c lookupInBases() to find tag members /// of the given name within a C++ class hierarchy. The user data pointer /// is an opaque \c DeclarationName pointer. - static bool FindTagMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name); + static bool FindTagMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name. @@ -853,8 +856,8 @@ public: /// This callback can be used with \c lookupInBases() to find members /// of the given name within a C++ class hierarchy. The user data pointer /// is an opaque \c DeclarationName pointer. - static bool FindOrdinaryMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name); + static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. @@ -862,7 +865,7 @@ public: /// This callback can be used with \c lookupInBases() to find membes of /// the given name within a C++ class hierarchy that can occur within /// nested-name-specifiers. - static bool FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier, + static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); @@ -1244,6 +1247,11 @@ public: /// used for user-defined conversions. bool isConvertingConstructor(bool AllowExplicit) const; + /// \brief Determine whether this is a member template specialization that + /// looks like a copy constructor. Such constructors are never used to copy + /// an object. + bool isCopyConstructorLikeSpecialization() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == CXXConstructor; @@ -1261,13 +1269,6 @@ public: /// }; /// @endcode class CXXDestructorDecl : public CXXMethodDecl { -public: - enum KindOfObjectToDestroy { - VBASE = 0x1, - DRCTNONVBASE = 0x2, - ANYBASE = 0x3 - }; -private: /// ImplicitlyDefined - Whether this destructor was implicitly /// defined by the compiler. When false, the destructor was defined /// by the user. In C++03, this flag will have the same value as @@ -1276,24 +1277,15 @@ private: /// @c !Implicit && ImplicitlyDefined. bool ImplicitlyDefined : 1; - /// Support for base and member destruction. - /// BaseOrMemberDestructions - The arguments used to destruct the base - /// or member. Each uintptr_t value represents one of base classes (either - /// virtual or direct non-virtual base), or non-static data member - /// to be destroyed. The low two bits encode the kind of object - /// being destroyed. - uintptr_t *BaseOrMemberDestructions; - unsigned NumBaseOrMemberDestructions; - + FunctionDecl *OperatorDelete; + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline), - ImplicitlyDefined(false), - BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) { + ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } - virtual void Destroy(ASTContext& C); public: static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -1319,95 +1311,8 @@ public: ImplicitlyDefined = ID; } - /// destr_iterator - Iterates through the member/base destruction list. - - /// destr_const_iterator - Iterates through the member/base destruction list. - typedef uintptr_t const destr_const_iterator; - - /// destr_begin() - Retrieve an iterator to the first destructed member/base. - uintptr_t* destr_begin() { - return BaseOrMemberDestructions; - } - /// destr_begin() - Retrieve an iterator to the first destructed member/base. - uintptr_t* destr_begin() const { - return BaseOrMemberDestructions; - } - - /// destr_end() - Retrieve an iterator past the last destructed member/base. - uintptr_t* destr_end() { - return BaseOrMemberDestructions + NumBaseOrMemberDestructions; - } - /// destr_end() - Retrieve an iterator past the last destructed member/base. - uintptr_t* destr_end() const { - return BaseOrMemberDestructions + NumBaseOrMemberDestructions; - } - - /// getNumBaseOrMemberDestructions - Number of base and non-static members - /// to destroy. - unsigned getNumBaseOrMemberDestructions() const { - return NumBaseOrMemberDestructions; - } - - /// setNumBaseOrMemberDestructions - Set number of base and non-static members - /// to destroy. - void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) { - NumBaseOrMemberDestructions = numBaseOrMemberDestructions; - } - - /// getBaseOrMemberToDestroy - get the generic 'member' representing either - /// the field or a base class. - uintptr_t* getBaseOrMemberToDestroy() const { - return BaseOrMemberDestructions; - } - - /// setBaseOrMemberToDestroy - set the generic 'member' representing either - /// the field or a base class. - void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) { - BaseOrMemberDestructions = baseOrMemberDestructions; - } - - /// isVbaseToDestroy - returns true, if object is virtual base. - bool isVbaseToDestroy(uintptr_t Vbase) const { - return (Vbase & VBASE) != 0; - } - /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual - /// base. - bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const { - return (DrctNonVbase & DRCTNONVBASE) != 0; - } - /// isAnyBaseToDestroy - returns true, if object is any base (virtual or - /// direct non-virtual) - bool isAnyBaseToDestroy(uintptr_t AnyBase) const { - return (AnyBase & ANYBASE) != 0; - } - /// isMemberToDestroy - returns true if object is a non-static data member. - bool isMemberToDestroy(uintptr_t Member) const { - return (Member & ANYBASE) == 0; - } - /// getAnyBaseClassToDestroy - Get the type for the given base class object. - Type *getAnyBaseClassToDestroy(uintptr_t Base) const { - if (isAnyBaseToDestroy(Base)) - return reinterpret_cast<Type*>(Base & ~0x03); - return 0; - } - /// getMemberToDestroy - Get the member for the given object. - FieldDecl *getMemberToDestroy(uintptr_t Member) const { - if (isMemberToDestroy(Member)) - return reinterpret_cast<FieldDecl *>(Member); - return 0; - } - /// getVbaseClassToDestroy - Get the virtual base. - Type *getVbaseClassToDestroy(uintptr_t Vbase) const { - if (isVbaseToDestroy(Vbase)) - return reinterpret_cast<Type*>(Vbase & ~0x01); - return 0; - } - /// getDirectNonVBaseClassToDestroy - Get the virtual base. - Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const { - if (isDirectNonVBaseToDestroy(Base)) - return reinterpret_cast<Type*>(Base & ~0x02); - return 0; - } + void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; } + const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { @@ -1739,6 +1644,56 @@ public: static bool classof(const NamespaceAliasDecl *D) { return true; } }; +/// UsingShadowDecl - Represents a shadow declaration introduced into +/// a scope by a (resolved) using declaration. For example, +/// +/// namespace A { +/// void foo(); +/// } +/// namespace B { +/// using A::foo(); // <- a UsingDecl +/// // Also creates a UsingShadowDecl for A::foo in B +/// } +/// +class UsingShadowDecl : public NamedDecl { + /// The referenced declaration. + NamedDecl *Underlying; + + /// The using declaration which introduced this decl. + UsingDecl *Using; + + UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) + : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()), + Underlying(Target), Using(Using) { + IdentifierNamespace = Target->getIdentifierNamespace(); + setImplicit(); + } + +public: + static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) { + return new (C) UsingShadowDecl(DC, Loc, Using, Target); + } + + /// Gets the underlying declaration which has been brought into the + /// local scope. + NamedDecl *getTargetDecl() const { + return Underlying; + } + + /// Gets the using declaration to which this declaration is tied. + UsingDecl *getUsingDecl() const { + return Using; + } + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UsingShadow; + } + static bool classof(const UsingShadowDecl *D) { return true; } +}; + /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { @@ -1746,29 +1701,26 @@ class UsingDecl : public NamedDecl { /// preceding the declaration name. SourceRange NestedNameRange; - /// \brief The source location of the target declaration name. - SourceLocation TargetNameLocation; - /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; - /// \brief Target declaration. - NamedDecl* TargetDecl; - /// \brief Target nested name specifier. - NestedNameSpecifier* TargetNestedNameDecl; + NestedNameSpecifier* TargetNestedName; + + /// \brief The collection of shadow declarations associated with + /// this using declaration. This set can change as a class is + /// processed. + llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows; // \brief Has 'typename' keyword. bool IsTypeName; UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, - SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target, - NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) - : NamedDecl(Decl::Using, DC, L, Target->getDeclName()), - NestedNameRange(NNR), TargetNameLocation(TargetNL), - UsingLocation(UL), TargetDecl(Target), - TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) { - this->IdentifierNamespace = TargetDecl->getIdentifierNamespace(); + SourceLocation UL, NestedNameSpecifier* TargetNNS, + DeclarationName Name, bool IsTypeNameArg) + : NamedDecl(Decl::Using, DC, L, Name), + NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), + IsTypeName(IsTypeNameArg) { } public: @@ -1776,28 +1728,37 @@ public: /// preceding the namespace name. SourceRange getNestedNameRange() { return NestedNameRange; } - /// \brief Returns the source location of the target declaration name. - SourceLocation getTargetNameLocation() { return TargetNameLocation; } - /// \brief Returns the source location of the "using" location itself. SourceLocation getUsingLocation() { return UsingLocation; } - /// \brief getTargetDecl - Returns target specified by using-decl. - NamedDecl *getTargetDecl() { return TargetDecl; } - const NamedDecl *getTargetDecl() const { return TargetDecl; } - /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameDecl() { - return TargetNestedNameDecl; + return TargetNestedName; } /// isTypeName - Return true if using decl has 'typename'. bool isTypeName() const { return IsTypeName; } + typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator; + shadow_iterator shadow_begin() const { return Shadows.begin(); } + shadow_iterator shadow_end() const { return Shadows.end(); } + + void addShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.insert(S)) { + assert(false && "declaration already in set"); + } + } + void removeShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.erase(S)) { + assert(false && "declaration not in set"); + } + } + static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, SourceRange NNR, SourceLocation TargetNL, - SourceLocation UL, NamedDecl* Target, - NestedNameSpecifier* TargetNNS, bool IsTypeNameArg); + SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, + NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); static bool classof(const Decl *D) { return D->getKind() == Decl::Using; @@ -1805,31 +1766,88 @@ public: static bool classof(const UsingDecl *D) { return true; } }; -/// UnresolvedUsingDecl - Represents a using declaration whose name can not -/// yet be resolved. -class UnresolvedUsingDecl : public NamedDecl { +/// UnresolvedUsingValueDecl - Represents a dependent using +/// declaration which was not marked with 'typename'. Unlike +/// non-dependent using declarations, these *only* bring through +/// non-types; otherwise they would break two-phase lookup. +/// +/// template <class T> class A : public Base<T> { +/// using Base<T>::foo; +/// }; +class UnresolvedUsingValueDecl : public ValueDecl { /// \brief The source range that covers the nested-name-specifier /// preceding the declaration name. SourceRange TargetNestedNameRange; - /// \brief The source location of the target declaration name. - SourceLocation TargetNameLocation; + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; NestedNameSpecifier *TargetNestedNameSpecifier; - DeclarationName TargetName; + UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, + SourceLocation UsingLoc, SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName) + : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TargetNestedNameSpecifier(TargetNNS) + { } - // \brief Has 'typename' keyword. - bool IsTypeName; +public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, DeclarationName TargetName, - bool IsTypeNameArg) - : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName), - TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc), - TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName), - IsTypeName(IsTypeNameArg) { } + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + static UnresolvedUsingValueDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UnresolvedUsingValue; + } + static bool classof(const UnresolvedUsingValueDecl *D) { return true; } +}; + +/// UnresolvedUsingTypenameDecl - Represents a dependent using +/// declaration which was marked with 'typename'. +/// +/// template <class T> class A : public Base<T> { +/// using typename Base<T>::foo; +/// }; +/// +/// The type associated with a unresolved using typename decl is +/// currently always a typename type. +class UnresolvedUsingTypenameDecl : public TypeDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange TargetNestedNameRange; + + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; + + /// \brief The source location of the 'typename' keyword + SourceLocation TypenameLocation; + + NestedNameSpecifier *TargetNestedNameSpecifier; + + UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, IdentifierInfo *TargetName) + : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) + { } public: /// \brief Returns the source range that covers the nested-name-specifier @@ -1841,26 +1859,22 @@ public: return TargetNestedNameSpecifier; } - /// \brief Returns the source location of the target declaration name. - SourceLocation getTargetNameLocation() const { return TargetNameLocation; } + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } - /// \brief Returns the source location of the target declaration name. - DeclarationName getTargetName() const { return TargetName; } - - bool isTypeName() const { return IsTypeName; } + /// \brief Returns the source location of the 'typename' keyword. + SourceLocation getTypenameLoc() const { return TypenameLocation; } - static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, - DeclarationName TargetName, - bool IsTypeNameArg); + static UnresolvedUsingTypenameDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); static bool classof(const Decl *D) { - return D->getKind() == Decl::UnresolvedUsing; + return D->getKind() == Decl::UnresolvedUsingTypename; } - static bool classof(const UnresolvedUsingDecl *D) { return true; } + static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } }; /// StaticAssertDecl - Represents a C++0x static_assert declaration. diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index d9e40d4789073..c2b48cee36f44 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -14,8 +14,9 @@ #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclCXX.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 3ef3cc3f09753..ec1b3b055cabd 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -81,6 +81,7 @@ ABSTRACT_DECL(Named, Decl) DECL(NamespaceAlias, NamedDecl) ABSTRACT_DECL(Type, NamedDecl) DECL(Typedef, TypeDecl) + DECL(UnresolvedUsingTypename, TypeDecl) ABSTRACT_DECL(Tag, TypeDecl) DECL(Enum, TagDecl) DECL(Record, TagDecl) @@ -91,6 +92,7 @@ ABSTRACT_DECL(Named, Decl) DECL(TemplateTypeParm, TypeDecl) ABSTRACT_DECL(Value, NamedDecl) DECL(EnumConstant, ValueDecl) + DECL(UnresolvedUsingValue, ValueDecl) ABSTRACT_DECL(Declarator, ValueDecl) DECL(Function, DeclaratorDecl) DECL(CXXMethod, FunctionDecl) @@ -109,7 +111,7 @@ ABSTRACT_DECL(Named, Decl) DECL(ClassTemplate, TemplateDecl) DECL(TemplateTemplateParm, TemplateDecl) DECL(Using, NamedDecl) - DECL(UnresolvedUsing, NamedDecl) + DECL(UsingShadow, NamedDecl) DECL(ObjCMethod, NamedDecl) DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index bcd28eab039fe..13193ffab55ed 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -718,10 +718,22 @@ public: /// @class NSCursor, NSImage, NSPasteboard, NSWindow; /// class ObjCClassDecl : public Decl { - ObjCList<ObjCInterfaceDecl> ForwardDecls; +public: + class ObjCClassRef { + ObjCInterfaceDecl *ID; + SourceLocation L; + public: + ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {} + SourceLocation getLocation() const { return L; } + ObjCInterfaceDecl *getInterface() const { return ID; } + }; +private: + ObjCClassRef *ForwardDecls; + unsigned NumDecls; ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C); + ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, + unsigned nElts, ASTContext &C); virtual ~ObjCClassDecl() {} public: @@ -730,17 +742,19 @@ public: static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts = 0, + const SourceLocation *Locs = 0, unsigned nElts = 0); + + virtual SourceRange getSourceRange() const; - typedef ObjCList<ObjCInterfaceDecl>::iterator iterator; - iterator begin() const { return ForwardDecls.begin(); } - iterator end() const { return ForwardDecls.end(); } - unsigned size() const { return ForwardDecls.size(); } + typedef const ObjCClassRef* iterator; + iterator begin() const { return ForwardDecls; } + iterator end() const { return ForwardDecls + NumDecls; } + unsigned size() const { return NumDecls; } /// setClassList - Set the list of forward classes. - void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) { - ForwardDecls.set(List, Num, C); - } + void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num); static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } static bool classof(const ObjCClassDecl *D) { return true; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f1a27933a1b37..14f666005cd62 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -699,13 +699,13 @@ class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { /// \brief The default template argument, if any. - Expr *DefaultArgument; + TemplateArgumentLoc DefaultArgument; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(0) + TemplateParmPosition(D, P), DefaultArgument() { } public: @@ -720,16 +720,17 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument; } + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); + } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument; } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } /// \brief Set the default argument for this template parameter. - void setDefaultArgument(Expr *DefArg) { + void setDefaultArgument(const TemplateArgumentLoc &DefArg) { DefaultArgument = DefArg; } diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index ed4ac6b5d4e74..a30f6e860dde9 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -176,7 +176,6 @@ public: /// getNameKind - Determine what kind of name this is. NameKind getNameKind() const; - /// getName - Retrieve the human-readable string for this name. std::string getAsString() const; @@ -249,6 +248,8 @@ public: static DeclarationName getTombstoneMarker() { return DeclarationName(uintptr_t(-2)); } + + void dump() const; }; /// Ordering on two declaration names. If both names are identifiers, diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2a87f5883588b..dfc5b13f28d30 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -87,7 +87,7 @@ public: // type. Additionally, inspect Expr::isLvalue to determine whether // an expression that is adjusted in this manner should be // considered an lvalue. - assert((TR.isNull() || !TR->isReferenceType()) && + assert((t.isNull() || !t->isReferenceType()) && "Expressions can't have reference type"); TR = t; @@ -250,6 +250,12 @@ public: /// folded, but discard the result. bool isEvaluatable(ASTContext &Ctx) const; + /// HasSideEffects - This routine returns true for all those expressions + /// which must be evaluated each time and must not be optimization away + /// or evaluated at compile time. Example is a function call, volatile + /// variable read. + bool HasSideEffects(ASTContext &Ctx) const; + /// EvaluateAsInt - Call Evaluate and return the folded integer. This /// must be called on an expression that constant folds to an integer. llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const; @@ -1513,6 +1519,9 @@ public: /// CK_NoOp - Used for const_cast. CK_NoOp, + /// CK_BaseToDerived - Base to derived class casts. + CK_BaseToDerived, + /// CK_DerivedToBase - Derived to base class casts. CK_DerivedToBase, diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 5931a3fcf984f..9e6fd4fd065b8 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -95,6 +95,8 @@ public: /// operation would return "x". Expr *getImplicitObjectArgument(); + virtual SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 5f318ba0b33bd..9b1c640a40b24 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -15,6 +15,8 @@ #define LLVM_CLANG_AST_LAYOUTINFO_H #include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/DeclCXX.h" namespace clang { class ASTContext; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 1e6871ff3b9c5..867932332d097 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_REDECLARABLE_H #include "llvm/ADT/PointerIntPair.h" +#include <iterator> namespace clang { @@ -23,6 +24,8 @@ template<typename decl_type> class Redeclarable { protected: + // FIXME: PointerIntPair is a value class that should not be inherited from. + // This should change to using containment. struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { DeclLink(decl_type *D, bool isLatest) : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index bb14c62d7770c..6db095872b0e8 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/Support/ErrorHandling.h" #include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" namespace llvm { class FoldingSetNodeID; @@ -48,21 +49,27 @@ class TemplateArgument { public: /// \brief The type of template argument we're storing. enum ArgKind { + /// \brief Represents an empty template argument, e.g., one that has not + /// been deduced. Null = 0, /// The template argument is a type. Its value is stored in the /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, + Type, + /// The template argument is a declaration that was provided for a pointer + /// or reference non-type template parameter. + Declaration, + /// The template argument is an integral value stored in an llvm::APSInt + /// that was provided for an integral non-type template parameter. + Integral, + /// The template argument is a template name that was provided for a + /// template template parameter. + Template, /// The template argument is a value- or type-dependent expression /// stored in an Expr*. - Expression = 4, - + Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. - Pack = 5 + Pack } Kind; /// \brief Construct an empty, invalid template argument. @@ -82,12 +89,21 @@ public: } /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) - : Kind(Integral) { + TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { new (Integer.Value) llvm::APSInt(Value); Integer.Type = Type.getAsOpaquePtr(); } + /// \brief Construct a template argument that is a template. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + TemplateArgument(TemplateName Name) : Kind(Template) { + TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -172,6 +188,15 @@ public: return reinterpret_cast<Decl *>(TypeOrValue); } + /// \brief Retrieve the template argument as a template name. + TemplateName getAsTemplate() const { + if (Kind != Template) + return TemplateName(); + + return TemplateName::getFromVoidPointer( + reinterpret_cast<void *> (TypeOrValue)); + } + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) @@ -242,13 +267,18 @@ private: union { Expr *Expression; DeclaratorInfo *Declarator; + struct { + unsigned QualifierRange[2]; + unsigned TemplateNameLoc; + } Template; }; #ifndef NDEBUG enum Kind { K_None, K_DeclaratorInfo, - K_Expression + K_Expression, + K_Template } Kind; #endif @@ -273,6 +303,17 @@ public: , Kind(K_Expression) #endif {} + + TemplateArgumentLocInfo(SourceRange QualifierRange, + SourceLocation TemplateNameLoc) +#ifndef NDEBUG + : Kind(K_Template) +#endif + { + Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); + Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + } DeclaratorInfo *getAsDeclaratorInfo() const { assert(Kind == K_DeclaratorInfo); @@ -284,6 +325,18 @@ public: return Expression; } + SourceRange getTemplateQualifierRange() const { + assert(Kind == K_Template); + return SourceRange( + SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), + SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + } + + SourceLocation getTemplateNameLoc() const { + assert(Kind == K_Template); + return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + } + #ifndef NDEBUG void validateForArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { @@ -294,6 +347,9 @@ public: case TemplateArgument::Declaration: assert(Kind == K_Expression); break; + case TemplateArgument::Template: + assert(Kind == K_Template); + break; case TemplateArgument::Integral: case TemplateArgument::Pack: assert(Kind == K_None); @@ -329,8 +385,18 @@ public: assert(Argument.getKind() == TemplateArgument::Expression); } - /// \brief - Fetches the start location of the argument. + TemplateArgumentLoc(const TemplateArgument &Argument, + SourceRange QualifierRange, + SourceLocation TemplateNameLoc) + : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { + assert(Argument.getKind() == TemplateArgument::Template); + } + + /// \brief - Fetches the primary location of the argument. SourceLocation getLocation() const { + if (Argument.getKind() == TemplateArgument::Template) + return getTemplateNameLoc(); + return getSourceRange().getBegin(); } @@ -359,6 +425,16 @@ public: assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); } + + SourceRange getTemplateQualifierRange() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateQualifierRange(); + } + + SourceLocation getTemplateNameLoc() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateNameLoc(); + } }; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index daa814739182f..c28bafe9a30f1 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -396,10 +396,6 @@ class QualType { llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, Qualifiers::FastWidth> Value; - bool hasExtQuals() const { - return Value.getPointer().is<const ExtQuals*>(); - } - const ExtQuals *getExtQualsUnsafe() const { return Value.getPointer().get<const ExtQuals*>(); } @@ -408,6 +404,8 @@ class QualType { return Value.getPointer().get<const Type*>(); } + QualType getUnqualifiedTypeSlow() const; + friend class QualifierCollector; public: QualType() {} @@ -417,14 +415,14 @@ public: QualType(const ExtQuals *Ptr, unsigned Quals) : Value(Ptr, Quals) {} - unsigned getFastQualifiers() const { return Value.getInt(); } - void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); } + unsigned getLocalFastQualifiers() const { return Value.getInt(); } + void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } /// Retrieves a pointer to the underlying (unqualified) type. /// This should really return a const Type, but it's not worth /// changing all the users right now. Type *getTypePtr() const { - if (hasNonFastQualifiers()) + if (hasLocalNonFastQualifiers()) return const_cast<Type*>(getExtQualsUnsafe()->getBaseType()); return const_cast<Type*>(getTypePtrUnsafe()); } @@ -452,41 +450,81 @@ public: return Value.getPointer().isNull(); } - bool isConstQualified() const { - return (getFastQualifiers() & Qualifiers::Const); + /// \brief Determine whether this particular QualType instance has the + /// "const" qualifier set, without looking through typedefs that may have + /// added "const" at a different level. + bool isLocalConstQualified() const { + return (getLocalFastQualifiers() & Qualifiers::Const); } - bool isRestrictQualified() const { - return (getFastQualifiers() & Qualifiers::Restrict); + + /// \brief Determine whether this type is const-qualified. + bool isConstQualified() const; + + /// \brief Determine whether this particular QualType instance has the + /// "restrict" qualifier set, without looking through typedefs that may have + /// added "restrict" at a different level. + bool isLocalRestrictQualified() const { + return (getLocalFastQualifiers() & Qualifiers::Restrict); } - bool isVolatileQualified() const { - return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); + + /// \brief Determine whether this type is restrict-qualified. + bool isRestrictQualified() const; + + /// \brief Determine whether this particular QualType instance has the + /// "volatile" qualifier set, without looking through typedefs that may have + /// added "volatile" at a different level. + bool isLocalVolatileQualified() const { + return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); } - // Determines whether this type has any direct qualifiers. - bool hasQualifiers() const { - return getFastQualifiers() || hasNonFastQualifiers(); + /// \brief Determine whether this type is volatile-qualified. + bool isVolatileQualified() const; + + /// \brief Determine whether this particular QualType instance has any + /// qualifiers, without looking through any typedefs that might add + /// qualifiers at a different level. + bool hasLocalQualifiers() const { + return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); } - bool hasNonFastQualifiers() const { - return hasExtQuals(); + /// \brief Determine whether this type has any qualifiers. + bool hasQualifiers() const; + + /// \brief Determine whether this particular QualType instance has any + /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType + /// instance. + bool hasLocalNonFastQualifiers() const { + return Value.getPointer().is<const ExtQuals*>(); } - // Retrieves the set of qualifiers belonging to this type. - Qualifiers getQualifiers() const { + /// \brief Retrieve the set of qualifiers local to this particular QualType + /// instance, not including any qualifiers acquired through typedefs or + /// other sugar. + Qualifiers getLocalQualifiers() const { Qualifiers Quals; - if (hasNonFastQualifiers()) + if (hasLocalNonFastQualifiers()) Quals = getExtQualsUnsafe()->getQualifiers(); - Quals.addFastQualifiers(getFastQualifiers()); + Quals.addFastQualifiers(getLocalFastQualifiers()); return Quals; } - // Retrieves the CVR qualifiers of this type. - unsigned getCVRQualifiers() const { - unsigned CVR = getFastQualifiers(); - if (isVolatileQualified()) CVR |= Qualifiers::Volatile; + /// \brief Retrieve the set of qualifiers applied to this type. + Qualifiers getQualifiers() const; + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// local to this particular QualType instance, not including any qualifiers + /// acquired through typedefs or other sugar. + unsigned getLocalCVRQualifiers() const { + unsigned CVR = getLocalFastQualifiers(); + if (isLocalVolatileQualified()) + CVR |= Qualifiers::Volatile; return CVR; } + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// applied to this type. + unsigned getCVRQualifiers() const; + bool isConstant(ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); } @@ -508,6 +546,9 @@ public: Value.setInt(Value.getInt() | TQs); } + // FIXME: The remove* functions are semantically broken, because they might + // not remove a qualifier stored on a typedef. Most of the with* functions + // have the same problem. void removeConst(); void removeVolatile(); void removeRestrict(); @@ -540,8 +581,21 @@ public: return T; } - QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); } + /// \brief Return this type with all of the instance-specific qualifiers + /// removed, but without removing any qualifiers that may have been applied + /// through typedefs. + QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } + /// \brief Return the unqualified form of the given type, which might be + /// desugared to eliminate qualifiers introduced via typedefs. + QualType getUnqualifiedType() const { + QualType T = getLocalUnqualifiedType(); + if (!T.hasQualifiers()) + return T; + + return getUnqualifiedTypeSlow(); + } + bool isMoreQualifiedThan(QualType Other) const; bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; @@ -892,8 +946,6 @@ public: QualType getCanonicalTypeInternal() const { return CanonicalType; } void dump() const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const = 0; static bool classof(const Type *) { return true; } }; @@ -963,8 +1015,21 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; + bool isInteger() const { + return TypeKind >= Bool && TypeKind <= Int128; + } + + bool isSignedInteger() const { + return TypeKind >= Char_S && TypeKind <= Int128; + } + + bool isUnsignedInteger() const { + return TypeKind >= Bool && TypeKind <= UInt128; + } + + bool isFloatingPoint() const { + return TypeKind >= Float && TypeKind <= LongDouble; + } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } static bool classof(const BuiltinType *) { return true; } @@ -988,9 +1053,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; } static bool classof(const FixedWidthIntType *) { return true; } }; @@ -1008,9 +1070,6 @@ class ComplexType : public Type, public llvm::FoldingSetNode { public: QualType getElementType() const { return ElementType; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1036,9 +1095,6 @@ class PointerType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - QualType getPointeeType() const { return PointeeType; } bool isSugared() const { return false; } @@ -1071,9 +1127,6 @@ public: // Get the pointee type. Pointee is required to always be a function type. QualType getPointeeType() const { return PointeeType; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1157,9 +1210,6 @@ class LValueReferenceType : public ReferenceType { {} friend class ASTContext; // ASTContext creates these public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1177,9 +1227,6 @@ class RValueReferenceType : public ReferenceType { } friend class ASTContext; // ASTContext creates these public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1209,9 +1256,6 @@ public: const Type *getClass() const { return Class; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1302,9 +1346,6 @@ protected: friend class ASTContext; // ASTContext creates these. public: const llvm::APInt &getSize() const { return Size; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1336,9 +1377,6 @@ class IncompleteArrayType : public ArrayType { : ArrayType(IncompleteArray, et, can, sm, tq) {} friend class ASTContext; // ASTContext creates these. public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1402,9 +1440,6 @@ public: SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1458,9 +1493,6 @@ public: SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1510,9 +1542,6 @@ public: QualType getElementType() const { return ElementType; } SourceLocation getAttributeLoc() const { return loc; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1555,9 +1584,6 @@ public: QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return NumElements; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1633,9 +1659,6 @@ public: return unsigned(idx-1) < NumElements; return false; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1699,9 +1722,6 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { public: // No additional state past what FunctionType provides. - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1812,9 +1832,6 @@ public: return exception_begin() + NumExceptions; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1856,9 +1873,6 @@ public: bool isSugared() const { return true; } QualType desugar() const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } static bool classof(const TypedefType *) { return true; } }; @@ -1879,9 +1893,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } static bool classof(const TypeOfExprType *) { return true; } }; @@ -1924,9 +1935,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } static bool classof(const TypeOfType *) { return true; } }; @@ -1953,9 +1961,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return !isDependentType(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } static bool classof(const DecltypeType *) { return true; } }; @@ -2000,9 +2005,6 @@ public: bool isBeingDefined() const { return decl.getInt(); } void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } @@ -2117,9 +2119,6 @@ public: } } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getUnderlyingType(), getTagKind()); } @@ -2155,9 +2154,6 @@ public: bool isParameterPack() const { return ParameterPack; } IdentifierInfo *getName() const { return Name; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2211,9 +2207,6 @@ public: return getCanonicalTypeInternal(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return true; } QualType desugar() const { return getReplacementType(); } @@ -2309,9 +2302,6 @@ public: /// \precondition @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return !isDependentType(); } QualType desugar() const { return getCanonicalTypeInternal(); } @@ -2363,9 +2353,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, NNS, NamedType); } @@ -2440,9 +2427,6 @@ public: return Name.dyn_cast<const TemplateSpecializationType *>(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2493,9 +2477,6 @@ public: qual_iterator qual_end() const { return Protocols.end(); } bool qual_empty() const { return Protocols.size() == 0; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2581,8 +2562,6 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType T, ObjCProtocolDecl **protocols, unsigned NumProtocols); - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } @@ -2604,8 +2583,8 @@ public: /// Collect any qualifiers on the given type and return an /// unqualified type. const Type *strip(QualType QT) { - addFastQualifiers(QT.getFastQualifiers()); - if (QT.hasNonFastQualifiers()) { + addFastQualifiers(QT.getLocalFastQualifiers()); + if (QT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = QT.getExtQualsUnsafe(); Context = &EQ->getContext(); addQualifiers(EQ->getQualifiers()); @@ -2627,18 +2606,51 @@ public: inline bool QualType::isCanonical() const { const Type *T = getTypePtr(); - if (hasQualifiers()) + if (hasLocalQualifiers()) return T->isCanonicalUnqualified() && !isa<ArrayType>(T); return T->isCanonicalUnqualified(); } inline bool QualType::isCanonicalAsParam() const { - if (hasQualifiers()) return false; + if (hasLocalQualifiers()) return false; const Type *T = getTypePtr(); return T->isCanonicalUnqualified() && !isa<FunctionType>(T) && !isa<ArrayType>(T); } +inline bool QualType::isConstQualified() const { + return isLocalConstQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified(); +} + +inline bool QualType::isRestrictQualified() const { + return isLocalRestrictQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified(); +} + + +inline bool QualType::isVolatileQualified() const { + return isLocalVolatileQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified(); +} + +inline bool QualType::hasQualifiers() const { + return hasLocalQualifiers() || + getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers(); +} + +inline Qualifiers QualType::getQualifiers() const { + Qualifiers Quals = getLocalQualifiers(); + Quals.addQualifiers( + getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers()); + return Quals; +} + +inline unsigned QualType::getCVRQualifiers() const { + return getLocalCVRQualifiers() | + getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } @@ -2673,14 +2685,14 @@ inline void QualType::removeCVRQualifiers(unsigned Mask) { /// getAddressSpace - Return the address space of this type. inline unsigned QualType::getAddressSpace() const { - if (hasNonFastQualifiers()) { + if (hasLocalNonFastQualifiers()) { const ExtQuals *EQ = getExtQualsUnsafe(); if (EQ->hasAddressSpace()) return EQ->getAddressSpace(); } QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasNonFastQualifiers()) { + if (CT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = CT.getExtQualsUnsafe(); if (EQ->hasAddressSpace()) return EQ->getAddressSpace(); @@ -2695,14 +2707,14 @@ inline unsigned QualType::getAddressSpace() const { /// getObjCGCAttr - Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { - if (hasNonFastQualifiers()) { + if (hasLocalNonFastQualifiers()) { const ExtQuals *EQ = getExtQualsUnsafe(); if (EQ->hasObjCGCAttr()) return EQ->getObjCGCAttr(); } QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasNonFastQualifiers()) { + if (CT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = CT.getExtQualsUnsafe(); if (EQ->hasObjCGCAttr()) return EQ->getObjCGCAttr(); @@ -2780,28 +2792,26 @@ inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { return 0; } -// NOTE: All of these methods use "getUnqualifiedType" to strip off address -// space qualifiers if present. inline bool Type::isFunctionType() const { - return isa<FunctionType>(CanonicalType.getUnqualifiedType()); + return isa<FunctionType>(CanonicalType); } inline bool Type::isPointerType() const { - return isa<PointerType>(CanonicalType.getUnqualifiedType()); + return isa<PointerType>(CanonicalType); } inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } inline bool Type::isBlockPointerType() const { - return isa<BlockPointerType>(CanonicalType.getUnqualifiedType()); + return isa<BlockPointerType>(CanonicalType); } inline bool Type::isReferenceType() const { - return isa<ReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<ReferenceType>(CanonicalType); } inline bool Type::isLValueReferenceType() const { - return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<LValueReferenceType>(CanonicalType); } inline bool Type::isRValueReferenceType() const { - return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<RValueReferenceType>(CanonicalType); } inline bool Type::isFunctionPointerType() const { if (const PointerType* T = getAs<PointerType>()) @@ -2810,7 +2820,7 @@ inline bool Type::isFunctionPointerType() const { return false; } inline bool Type::isMemberPointerType() const { - return isa<MemberPointerType>(CanonicalType.getUnqualifiedType()); + return isa<MemberPointerType>(CanonicalType); } inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) @@ -2819,37 +2829,37 @@ inline bool Type::isMemberFunctionPointerType() const { return false; } inline bool Type::isArrayType() const { - return isa<ArrayType>(CanonicalType.getUnqualifiedType()); + return isa<ArrayType>(CanonicalType); } inline bool Type::isConstantArrayType() const { - return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()); + return isa<ConstantArrayType>(CanonicalType); } inline bool Type::isIncompleteArrayType() const { - return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType()); + return isa<IncompleteArrayType>(CanonicalType); } inline bool Type::isVariableArrayType() const { - return isa<VariableArrayType>(CanonicalType.getUnqualifiedType()); + return isa<VariableArrayType>(CanonicalType); } inline bool Type::isDependentSizedArrayType() const { - return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType()); + return isa<DependentSizedArrayType>(CanonicalType); } inline bool Type::isRecordType() const { - return isa<RecordType>(CanonicalType.getUnqualifiedType()); + return isa<RecordType>(CanonicalType); } inline bool Type::isAnyComplexType() const { - return isa<ComplexType>(CanonicalType.getUnqualifiedType()); + return isa<ComplexType>(CanonicalType); } inline bool Type::isVectorType() const { - return isa<VectorType>(CanonicalType.getUnqualifiedType()); + return isa<VectorType>(CanonicalType); } inline bool Type::isExtVectorType() const { - return isa<ExtVectorType>(CanonicalType.getUnqualifiedType()); + return isa<ExtVectorType>(CanonicalType); } inline bool Type::isObjCObjectPointerType() const { - return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType()); + return isa<ObjCObjectPointerType>(CanonicalType); } inline bool Type::isObjCInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType()); + return isa<ObjCInterfaceType>(CanonicalType); } inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) @@ -2875,7 +2885,7 @@ inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType(); } inline bool Type::isTemplateTypeParmType() const { - return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType()); + return isa<TemplateTypeParmType>(CanonicalType); } inline bool Type::isSpecificBuiltinType(unsigned K) const { @@ -2911,8 +2921,21 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } +// Helper class template that is used by Type::getAs to ensure that one does +// not try to look through a qualified type to get to an array type. +template<typename T, + bool isArrayType = (llvm::is_same<T, ArrayType>::value || + llvm::is_base_of<ArrayType, T>::value)> +struct ArrayType_cannot_be_used_with_getAs { }; + +template<typename T> +struct ArrayType_cannot_be_used_with_getAs<T, true>; + /// Member-template getAs<specific type>'. template <typename T> const T *Type::getAs() const { + ArrayType_cannot_be_used_with_getAs<T> at; + (void)at; + // If this is directly a T type, return it. if (const T *Ty = dyn_cast<T>(this)) return Ty; diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index da7857822e9c4..f08ca6bf469b4 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -58,7 +58,7 @@ public: : Ty(ty), Data(opaqueData) { } TypeLocClass getTypeLocClass() const { - if (getType().hasQualifiers()) return Qualified; + if (getType().hasLocalQualifiers()) return Qualified; return (TypeLocClass) getType()->getTypeClass(); } @@ -155,7 +155,7 @@ public: } static bool classof(const TypeLoc *TL) { - return !TL->getType().hasQualifiers(); + return !TL->getType().hasLocalQualifiers(); } static bool classof(const UnqualTypeLoc *TL) { return true; } }; @@ -196,11 +196,11 @@ public: /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getLocalDataSize() + - getFullDataSizeForType(getType().getUnqualifiedType()); + getFullDataSizeForType(getType().getLocalUnqualifiedType()); } static bool classof(const TypeLoc *TL) { - return TL->getType().hasQualifiers(); + return TL->getType().hasLocalQualifiers(); } static bool classof(const QualifiedTypeLoc *TL) { return true; } }; @@ -919,6 +919,10 @@ public: Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); break; + case TemplateArgument::Template: + Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + break; + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index 4e1fbaaf4c5ed..00e2b7f832192 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -17,6 +17,7 @@ #include "clang/AST/TypeLoc.h" #include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" namespace clang { |
