diff options
Diffstat (limited to 'include/clang/AST/Type.h')
-rw-r--r-- | include/clang/AST/Type.h | 84 |
1 files changed, 61 insertions, 23 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 72793651c4be..030c74c64089 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -871,6 +871,7 @@ public: bool isRecordType() const; bool isClassType() const; bool isStructureType() const; + bool isStructureOrClassType() const; bool isUnionType() const; bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. @@ -922,6 +923,11 @@ public: const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; + /// \brief Retrieves the CXXRecordDecl that this type refers to, either + /// because the type is a RecordType or because it is the injected-class-name + /// type of a class template or class template partial specialization. + CXXRecordDecl *getAsCXXRecordDecl() const; + // Member-template getAs<specific type>'. This scheme will eventually // replace the specific getAsXXXX methods above. // @@ -2433,8 +2439,11 @@ public: class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - // FIXME: Currently needed for profiling expressions; can we avoid this? - ASTContext &Context; + // The ASTContext is currently needed in order to profile expressions. + // FIXME: avoid this. + // + // The bool is whether this is a current instantiation. + llvm::PointerIntPair<ASTContext*, 1, bool> ContextAndCurrentInstantiation; /// \brief The name of the template being specialized. TemplateName Template; @@ -2445,6 +2454,7 @@ class TemplateSpecializationType TemplateSpecializationType(ASTContext &Context, TemplateName T, + bool IsCurrentInstantiation, const TemplateArgument *Args, unsigned NumArgs, QualType Canon); @@ -2476,6 +2486,12 @@ public: static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, const PrintingPolicy &Policy); + /// True if this template specialization type matches a current + /// instantiation in the context in which it is found. + bool isCurrentInstantiation() const { + return ContextAndCurrentInstantiation.getInt(); + } + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } @@ -2496,15 +2512,20 @@ public: /// \precondition @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; - bool isSugared() const { return !isDependentType(); } + bool isSugared() const { + return !isDependentType() || isCurrentInstantiation(); + } QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Template, getArgs(), NumArgs, Context); + Profile(ID, Template, isCurrentInstantiation(), getArgs(), NumArgs, + *ContextAndCurrentInstantiation.getPointer()); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, unsigned NumArgs, + bool IsCurrentInstantiation, + const TemplateArgument *Args, + unsigned NumArgs, ASTContext &Context); static bool classof(const Type *T) { @@ -2513,40 +2534,57 @@ public: static bool classof(const TemplateSpecializationType *T) { return true; } }; -/// \brief The injected class name of a C++ class template. Used to -/// record that a type was spelled with a bare identifier rather than -/// as a template-id; the equivalent for non-templated classes is just -/// RecordType. +/// \brief The injected class name of a C++ class template or class +/// template partial specialization. Used to record that a type was +/// spelled with a bare identifier rather than as a template-id; the +/// equivalent for non-templated classes is just RecordType. /// -/// For consistency, template instantiation turns these into RecordTypes. +/// Injected class name types are always dependent. Template +/// instantiation turns these into RecordTypes. /// -/// The desugared form is always a unqualified TemplateSpecializationType. -/// The canonical form is always either a TemplateSpecializationType -/// (when dependent) or a RecordType (otherwise). +/// Injected class name types are always canonical. This works +/// because it is impossible to compare an injected class name type +/// with the corresponding non-injected template type, for the same +/// reason that it is impossible to directly compare template +/// parameters from different dependent contexts: injected class name +/// types can only occur within the scope of a particular templated +/// declaration, and within that scope every template specialization +/// will canonicalize to the injected class name (when appropriate +/// according to the rules of the language). class InjectedClassNameType : public Type { CXXRecordDecl *Decl; - QualType UnderlyingType; + /// The template specialization which this type represents. + /// For example, in + /// template <class T> class A { ... }; + /// this is A<T>, whereas in + /// template <class X, class Y> class A<B<X,Y> > { ... }; + /// this is A<B<X,Y> >. + /// + /// It is always unqualified, always a template specialization type, + /// and always dependent. + QualType InjectedType; friend class ASTContext; // ASTContext creates these. - InjectedClassNameType(CXXRecordDecl *D, QualType TST, QualType Canon) - : Type(InjectedClassName, Canon, Canon->isDependentType()), - Decl(D), UnderlyingType(TST) { + friend class TagDecl; // TagDecl mutilates the Decl + InjectedClassNameType(CXXRecordDecl *D, QualType TST) + : Type(InjectedClassName, QualType(), true), + Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); - assert(TST->getCanonicalTypeInternal() == Canon); + assert(TST->isDependentType()); } public: - QualType getUnderlyingType() const { return UnderlyingType; } - const TemplateSpecializationType *getUnderlyingTST() const { - return cast<TemplateSpecializationType>(UnderlyingType.getTypePtr()); + QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { + return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } CXXRecordDecl *getDecl() const { return Decl; } - bool isSugared() const { return true; } - QualType desugar() const { return UnderlyingType; } + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == InjectedClassName; |