diff options
Diffstat (limited to 'include/clang/AST')
-rw-r--r-- | include/clang/AST/ASTContext.h | 82 | ||||
-rw-r--r-- | include/clang/AST/Attr.h | 1 | ||||
-rw-r--r-- | include/clang/AST/CXXInheritance.h | 3 | ||||
-rw-r--r-- | include/clang/AST/CanonicalType.h | 26 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 50 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 36 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 36 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 25 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 255 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 690 | ||||
-rw-r--r-- | include/clang/AST/TypeLocBuilder.h | 122 | ||||
-rw-r--r-- | include/clang/AST/TypeLocNodes.def | 46 | ||||
-rw-r--r-- | include/clang/AST/TypeLocVisitor.h | 44 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 5 |
14 files changed, 907 insertions, 514 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 106d568c9b240..30896c91a1432 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -81,12 +81,12 @@ class ASTContext { llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; + llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; llvm::FoldingSet<TypenameType> TypenameTypes; llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; @@ -143,6 +143,12 @@ class ASTContext { /// \brief The type for the C sigjmp_buf type. TypeDecl *sigjmp_bufDecl; + /// \brief Type for the Block descriptor for Blocks CodeGen. + RecordDecl *BlockDescriptorType; + + /// \brief Type for the Block descriptor for Blocks CodeGen. + RecordDecl *BlockDescriptorExtendedType; + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -390,9 +396,47 @@ public: /// of the specified type. QualType getBlockPointerType(QualType T); + /// This gets the struct used to keep track of the descriptor for pointer to + /// blocks. + QualType getBlockDescriptorType(); + + // Set the type for a Block descriptor type. + void setBlockDescriptorType(QualType T); + /// Get the BlockDescriptorType type, or NULL if it hasn't yet been built. + QualType getRawBlockdescriptorType() { + if (BlockDescriptorType) + return getTagDeclType(BlockDescriptorType); + return QualType(); + } + + /// This gets the struct used to keep track of the extended descriptor for + /// pointer to blocks. + QualType getBlockDescriptorExtendedType(); + + // Set the type for a Block descriptor extended type. + void setBlockDescriptorExtendedType(QualType T); + /// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been + /// built. + QualType getRawBlockdescriptorExtendedType() { + if (BlockDescriptorExtendedType) + return getTagDeclType(BlockDescriptorExtendedType); + return QualType(); + } + + /// This gets the struct used to keep track of pointer to blocks, complete + /// with captured variables. + QualType getBlockParmType(bool BlockHasCopyDispose, + llvm::SmallVector<const Expr *, 8> &BDRDs); + + /// This builds the struct used for __block variables. + QualType BuildByRefType(const char *DeclName, QualType Ty); + + /// Returns true iff we need copy/dispose helpers for the given type. + bool BlockRequiresCopying(QualType Ty); + /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. - QualType getLValueReferenceType(QualType T); + QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true); /// getRValueReferenceType - Return the uniqued reference to the type for an /// rvalue reference to the specified type. @@ -431,22 +475,6 @@ public: ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals); - /// getConstantArrayWithExprType - Return a reference to the type for a - /// constant array of the specified element type. - QualType getConstantArrayWithExprType(QualType EltTy, - const llvm::APInt &ArySize, - Expr *ArySizeExpr, - ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals, - SourceRange Brackets); - - /// getConstantArrayWithoutExprType - Return a reference to the type - /// for a constant array of the specified element type. - QualType getConstantArrayWithoutExprType(QualType EltTy, - const llvm::APInt &ArySize, - ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals); - /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts); @@ -485,6 +513,9 @@ public: /// specified typename decl. QualType getTypedefType(TypedefDecl *Decl); + QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, + QualType Replacement); + QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, IdentifierInfo *Name = 0); @@ -515,10 +546,6 @@ public: ObjCProtocolDecl **ProtocolList = 0, unsigned NumProtocols = 0); - QualType getObjCProtocolListType(QualType T, - ObjCProtocolDecl **Protocols, - unsigned NumProtocols); - /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); QualType getTypeOfType(QualType t); @@ -815,6 +842,12 @@ public: return T->getCanonicalTypeInternal().getTypePtr(); } + /// getCanonicalParamType - Return the canonical parameter type + /// corresponding to the specific potentially non-canonical one. + /// Qualifiers are stripped off, functions are turned into function + /// pointers, and arrays decay one level into pointers. + CanQualType getCanonicalParamType(QualType T); + /// \brief Determine whether the given types are equivalent. bool hasSameType(QualType T1, QualType T2) { return getCanonicalType(T1) == getCanonicalType(T2); @@ -1047,7 +1080,10 @@ public: /// \param T the type that will be the basis for type source info. This type /// should refer to how the declarator was written in source code, not to /// what type semantic analysis resolved the declarator to. - DeclaratorInfo *CreateDeclaratorInfo(QualType T); + /// + /// \param Size the size of the type info to create, or 0 if the size + /// should be calculated based on the type. + DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0); private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 6a5e3666a92c4..f7a47364a7f61 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -185,7 +185,6 @@ class AlignedAttr : public Attr { public: AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} - // FIXME: Should use addressable units, not bits, to match llvm /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index a57bcc184a936..7c826fe75d11e 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -63,7 +63,8 @@ struct CXXBasePathElement { /// structure, which captures both the link from a derived class to one of its /// direct bases and identification describing which base class /// subobject is being used. -struct CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { +class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { +public: /// \brief The set of declarations found inside this base class /// subobject. DeclContext::lookup_result Decls; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index d7ac76dd32e42..8b84bc2679976 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -487,30 +487,6 @@ struct CanProxyAdaptor<ConstantArrayType> }; template<> -struct CanProxyAdaptor<ConstantArrayWithExprType> - : public CanProxyBase<ConstantArrayWithExprType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) -}; - -template<> -struct CanProxyAdaptor<ConstantArrayWithoutExprType> - : public CanProxyBase<ConstantArrayWithoutExprType> { - LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, - getSizeModifier) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) -}; - -template<> struct CanProxyAdaptor<IncompleteArrayType> : public CanProxyBase<IncompleteArrayType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) @@ -684,7 +660,7 @@ CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { template<typename T> CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { - assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!"); + assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); assert((Other.isNull() || isa<T>(Other.getTypePtr())) && "Dynamic type does not meet the static type's requires"); CanQual<T> Result; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index f21541c3e7104..72ce0d852cfc5 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -47,6 +47,9 @@ class DeclaratorInfo { friend class ASTContext; DeclaratorInfo(QualType ty) : Ty(ty) { } public: + /// \brief Return the type wrapped by this type source info. + QualType getType() const { return Ty; } + /// \brief Return the TypeLoc wrapper for the type source info. TypeLoc getTypeLoc() const; }; @@ -93,28 +96,43 @@ public: /// name (C++ constructor, Objective-C selector, etc.). IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } + /// getName - Get the name of identifier for this declaration as a StringRef. + /// This requires that the declaration have a name and that it be a simple + /// identifier. + llvm::StringRef getName() const { + assert(Name.isIdentifier() && "Name is not a simple identifier"); + return getIdentifier() ? getIdentifier()->getName() : ""; + } + /// getNameAsCString - Get the name of identifier for this declaration as a /// C string (const char*). This requires that the declaration have a name /// and that it be a simple identifier. + // + // FIXME: Deprecated, move clients to getName(). const char *getNameAsCString() const { - assert(getIdentifier() && "Name is not a simple identifier"); - return getIdentifier()->getName(); + assert(Name.isIdentifier() && "Name is not a simple identifier"); + return getIdentifier() ? getIdentifier()->getNameStart() : ""; } - /// getDeclName - Get the actual, stored name of the declaration, - /// which may be a special name. - DeclarationName getDeclName() const { return Name; } - - /// \brief Set the name of this declaration. - void setDeclName(DeclarationName N) { Name = N; } - /// 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 /// manipulation, so it should be called only when performance doesn't matter. /// For simple declarations, getNameAsCString() should suffice. + // + // FIXME: This function should be renamed to indicate that it is not just an + // alternate form of getName(), and clients should move as appropriate. + // + // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { return Name.getAsString(); } + /// getDeclName - Get the actual, stored name of the declaration, + /// which may be a special name. + DeclarationName getDeclName() const { return Name; } + + /// \brief Set the name of this declaration. + void setDeclName(DeclarationName N) { Name = N; } + /// getQualifiedNameAsString - Returns human-readable qualified name for /// declaration, like A::B::i, for i being member of namespace A::B. /// If declaration is not member of context which can be named (record, @@ -604,7 +622,8 @@ public: /// \brief For a static data member that was instantiated from a static /// data member of a class template, set the template specialiation kind. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + void setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { @@ -1170,7 +1189,16 @@ public: /// \brief Determine what kind of template instantiation this function /// represents. - void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + void setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); + + /// \brief Retrieve the (first) point of instantiation of a function template + /// specialization or a member of a class template specialization. + /// + /// \returns the first point of instantiation, if this function was + /// instantiated from a template; otherwie, returns an invalid source + /// location. + SourceLocation getPointOfInstantiation() const; /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 9e88871565f1f..10db7030db18e 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -166,6 +166,15 @@ private: bool Used : 1; protected: + /// Access - Used by C++ decls for the access specifier. + // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum + unsigned Access : 2; + friend class CXXClassMemberWrapper; + + // PCHLevel - the "level" of precompiled header/AST file from which this + // declaration was built. + unsigned PCHLevel : 2; + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 16; @@ -177,16 +186,13 @@ private: #endif protected: - /// Access - Used by C++ decls for the access specifier. - // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum - unsigned Access : 2; - friend class CXXClassMemberWrapper; Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) { + Access(AS_none), PCHLevel(0), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { if (Decl::CollectingStats()) addDeclKind(DK); } @@ -274,6 +280,26 @@ public: bool isUsed() const { return Used; } void setUsed(bool U = true) { Used = U; } + /// \brief Retrieve the level of precompiled header from which this + /// declaration was generated. + /// + /// The PCH level of a declaration describes where the declaration originated + /// from. A PCH level of 0 indicates that the declaration was not from a + /// precompiled header. A PCH level of 1 indicates that the declaration was + /// from a top-level precompiled header; 2 indicates that the declaration + /// comes from a precompiled header on which the top-level precompiled header + /// depends, and so on. + unsigned getPCHLevel() const { return PCHLevel; } + + /// \brief The maximum PCH level that any declaration may have. + static const unsigned MaxPCHLevel = 3; + + /// \brief Set the PCH level of this declaration. + void setPCHLevel(unsigned Level) { + assert(Level < MaxPCHLevel && "PCH level exceeds the maximum"); + PCHLevel = Level; + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 2b12bb5c1b6d2..729a2f138303e 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -944,16 +944,29 @@ public: ObjCCategoryDecl *getCategoryClass() const; + /// getName - Get the name of identifier for the class interface associated + /// with this implementation as a StringRef. + // + // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean + // something different. + llvm::StringRef getName() const { + return Id ? Id->getNameStart() : ""; + } + /// getNameAsCString - Get the name of identifier for the class /// interface associated with this implementation as a C string /// (const char*). + // + // FIXME: Deprecated, move clients to getName(). const char *getNameAsCString() const { - return Id ? Id->getName() : ""; + return Id ? Id->getNameStart() : ""; } /// @brief Get the name of the class associated with this interface. + // + // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { - return Id ? Id->getName() : ""; + return getName(); } static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;} @@ -995,17 +1008,30 @@ public: return getClassInterface()->getIdentifier(); } + /// getName - Get the name of identifier for the class interface associated + /// with this implementation as a StringRef. + // + // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean + // something different. + llvm::StringRef getName() const { + assert(getIdentifier() && "Name is not a simple identifier"); + return getIdentifier()->getName(); + } + /// getNameAsCString - Get the name of identifier for the class /// interface associated with this implementation as a C string /// (const char*). + // + // FIXME: Move to StringRef API. const char *getNameAsCString() const { - assert(getIdentifier() && "Name is not a simple identifier"); - return getIdentifier()->getName(); + return getName().data(); } /// @brief Get the name of the class associated with this interface. + // + // FIXME: Move to StringRef API. std::string getNameAsString() const { - return getClassInterface()->getNameAsString(); + return getName(); } const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d5dff5065d49e..0d09ea325c319 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1399,7 +1399,27 @@ public: CK_IntegralToPointer, /// CK_PointerToIntegral - Pointer to integral - CK_PointerToIntegral + CK_PointerToIntegral, + + /// CK_ToVoid - Cast to void. + CK_ToVoid, + + /// CK_VectorSplat - Casting from an integer/floating type to an extended + /// vector type with the same element type as the src type. Splats the + /// src expression into the destination expression. + CK_VectorSplat, + + /// CK_IntegralCast - Casting between integral types of different size. + CK_IntegralCast, + + /// CK_IntegralToFloating - Integral to floating point. + CK_IntegralToFloating, + + /// CK_FloatingToIntegral - Floating point to integral. + CK_FloatingToIntegral, + + /// CK_FloatingCast - Casting between floating types of different size. + CK_FloatingCast }; private: @@ -1665,7 +1685,8 @@ public: /// predicates to categorize the respective opcodes. bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } - bool isShiftOp() const { return Opc == Shl || Opc == Shr; } + static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } + bool isShiftOp() const { return isShiftOp(Opc); } bool isBitwiseOp() const { return Opc >= And && Opc <= Or; } static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 89776b91fe4a8..db02a68a984dd 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -443,6 +443,9 @@ public: return getTypePtr(); } + bool isCanonical() const; + bool isCanonicalAsParam() const; + /// isNull - Return true if this QualType doesn't point to a type yet. bool isNull() const { return Value.getPointer().isNull(); @@ -702,7 +705,9 @@ protected: public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } - bool isCanonical() const { return CanonicalType.getTypePtr() == this; } + bool isCanonicalUnqualified() const { + return CanonicalType.getTypePtr() == this; + } /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. @@ -1089,19 +1094,50 @@ public: class ReferenceType : public Type, public llvm::FoldingSetNode { QualType PointeeType; + /// True if the type was originally spelled with an lvalue sigil. + /// This is never true of rvalue references but can also be false + /// on lvalue references because of C++0x [dcl.typedef]p9, + /// as follows: + /// + /// typedef int &ref; // lvalue, spelled lvalue + /// typedef int &&rvref; // rvalue + /// ref &a; // lvalue, inner ref, spelled lvalue + /// ref &&a; // lvalue, inner ref + /// rvref &a; // lvalue, inner ref, spelled lvalue + /// rvref &&a; // rvalue, inner ref + bool SpelledAsLValue; + + /// True if the inner type is a reference type. This only happens + /// in non-canonical forms. + bool InnerRef; + protected: - ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) : + ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) : Type(tc, CanonicalRef, Referencee->isDependentType()), - PointeeType(Referencee) { + PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), + InnerRef(Referencee->isReferenceType()) { } public: - QualType getPointeeType() const { return PointeeType; } + bool isSpelledAsLValue() const { return SpelledAsLValue; } + + QualType getPointeeTypeAsWritten() const { return PointeeType; } + QualType getPointeeType() const { + // FIXME: this might strip inner qualifiers; okay? + const ReferenceType *T = this; + while (T->InnerRef) + T = T->PointeeType->getAs<ReferenceType>(); + return T->PointeeType; + } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType()); + Profile(ID, PointeeType, SpelledAsLValue); } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) { + static void Profile(llvm::FoldingSetNodeID &ID, + QualType Referencee, + bool SpelledAsLValue) { ID.AddPointer(Referencee.getAsOpaquePtr()); + ID.AddBoolean(SpelledAsLValue); } static bool classof(const Type *T) { @@ -1114,9 +1150,10 @@ public: /// LValueReferenceType - C++ [dcl.ref] - Lvalue reference /// class LValueReferenceType : public ReferenceType { - LValueReferenceType(QualType Referencee, QualType CanonicalRef) : - ReferenceType(LValueReference, Referencee, CanonicalRef) { - } + LValueReferenceType(QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) : + ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) + {} friend class ASTContext; // ASTContext creates these public: virtual void getAsStringInternal(std::string &InnerString, @@ -1135,7 +1172,7 @@ public: /// class RValueReferenceType : public ReferenceType { RValueReferenceType(QualType Referencee, QualType CanonicalRef) : - ReferenceType(RValueReference, Referencee, CanonicalRef) { + ReferenceType(RValueReference, Referencee, CanonicalRef, false) { } friend class ASTContext; // ASTContext creates these public: @@ -1239,8 +1276,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || - T->getTypeClass() == ConstantArrayWithExpr || - T->getTypeClass() == ConstantArrayWithoutExpr || T->getTypeClass() == VariableArray || T->getTypeClass() == IncompleteArray || T->getTypeClass() == DependentSizedArray; @@ -1285,86 +1320,11 @@ public: ID.AddInteger(TypeQuals); } static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray || - T->getTypeClass() == ConstantArrayWithExpr || - T->getTypeClass() == ConstantArrayWithoutExpr; + return T->getTypeClass() == ConstantArray; } static bool classof(const ConstantArrayType *) { return true; } }; -/// ConstantArrayWithExprType - This class represents C arrays with a -/// constant size specified by means of an integer constant expression. -/// For example 'int A[sizeof(int)]' has ConstantArrayWithExprType where -/// the element type is 'int' and the size expression is 'sizeof(int)'. -/// These types are non-canonical. -class ConstantArrayWithExprType : public ConstantArrayType { - /// SizeExpr - The ICE occurring in the concrete syntax. - Expr *SizeExpr; - /// Brackets - The left and right array brackets. - SourceRange Brackets; - - ConstantArrayWithExprType(QualType et, QualType can, - const llvm::APInt &size, Expr *e, - ArraySizeModifier sm, unsigned tq, - SourceRange brackets) - : ConstantArrayType(ConstantArrayWithExpr, et, can, size, sm, tq), - SizeExpr(e), Brackets(brackets) {} - friend class ASTContext; // ASTContext creates these. - virtual void Destroy(ASTContext& C); - -public: - Expr *getSizeExpr() const { return SizeExpr; } - SourceRange getBracketsRange() const { return Brackets; } - 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); } - - static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArrayWithExpr; - } - static bool classof(const ConstantArrayWithExprType *) { return true; } - - void Profile(llvm::FoldingSetNodeID &ID) { - assert(0 && "Cannot unique ConstantArrayWithExprTypes."); - } -}; - -/// ConstantArrayWithoutExprType - This class represents C arrays with a -/// constant size that was not specified by an integer constant expression, -/// but inferred by static semantics. -/// For example 'int A[] = { 0, 1, 2 }' has ConstantArrayWithoutExprType. -/// These types are non-canonical: the corresponding canonical type, -/// having the size specified in an APInt object, is a ConstantArrayType. -class ConstantArrayWithoutExprType : public ConstantArrayType { - - ConstantArrayWithoutExprType(QualType et, QualType can, - const llvm::APInt &size, - ArraySizeModifier sm, unsigned tq) - : ConstantArrayType(ConstantArrayWithoutExpr, et, can, size, 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); } - - static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArrayWithoutExpr; - } - static bool classof(const ConstantArrayWithoutExprType *) { return true; } - - void Profile(llvm::FoldingSetNodeID &ID) { - assert(0 && "Cannot unique ConstantArrayWithoutExprTypes."); - } -}; - /// IncompleteArrayType - This class represents C arrays with an unspecified /// size. For example 'int A[]' has an IncompleteArrayType where the element /// type is 'int' and the size is unspecified. @@ -2219,6 +2179,59 @@ public: static bool classof(const TemplateTypeParmType *T) { return true; } }; +/// \brief Represents the result of substituting a type for a template +/// type parameter. +/// +/// Within an instantiated template, all template type parameters have +/// been replaced with these. They are used solely to record that a +/// type was originally written as a template type parameter; +/// therefore they are never canonical. +class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { + // The original type parameter. + const TemplateTypeParmType *Replaced; + + SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) + : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()), + Replaced(Param) { } + + friend class ASTContext; + +public: + IdentifierInfo *getName() const { return Replaced->getName(); } + + /// Gets the template parameter that was substituted for. + const TemplateTypeParmType *getReplacedParameter() const { + return Replaced; + } + + /// Gets the type that was substituted for the template + /// parameter. + QualType getReplacementType() const { + return getCanonicalTypeInternal(); + } + + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + + bool isSugared() const { return true; } + QualType desugar() const { return getReplacementType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getReplacedParameter(), getReplacementType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, + const TemplateTypeParmType *Replaced, + QualType Replacement) { + ID.AddPointer(Replaced); + ID.AddPointer(Replacement.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == SubstTemplateTypeParm; + } + static bool classof(const SubstTemplateTypeParmType *T) { return true; } +}; + /// \brief Represents the type of a template specialization as written /// in the source code. /// @@ -2453,9 +2466,9 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode { // List is sorted on protocol name. No protocol is enterred more than once. llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; - ObjCInterfaceType(ObjCInterfaceDecl *D, + ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, ObjCProtocolDecl **Protos, unsigned NumP) : - Type(ObjCInterface, QualType(), /*Dependent=*/false), + Type(ObjCInterface, Canonical, /*Dependent=*/false), Decl(D), Protocols(Protos, Protos+NumP) { } friend class ASTContext; // ASTContext creates these. public: @@ -2501,8 +2514,9 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { // List is sorted on protocol name. No protocol is entered more than once. llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; - ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : - Type(ObjCObjectPointer, QualType(), /*Dependent=*/false), + ObjCObjectPointerType(QualType Canonical, QualType T, + ObjCProtocolDecl **Protos, unsigned NumP) : + Type(ObjCObjectPointer, Canonical, /*Dependent=*/false), PointeeType(T), Protocols(Protos, Protos+NumP) { } friend class ASTContext; // ASTContext creates these. @@ -2567,49 +2581,6 @@ public: static bool classof(const ObjCObjectPointerType *) { return true; } }; -/// \brief An ObjC Protocol list that qualifies a type. -/// -/// This is used only for keeping detailed type source information, it should -/// not participate in the semantics of the type system. -/// The protocol list is not canonicalized. -class ObjCProtocolListType : public Type, public llvm::FoldingSetNode { - QualType BaseType; - - // List of protocols for this protocol conforming object type. - llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; - - ObjCProtocolListType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : - Type(ObjCProtocolList, QualType(), /*Dependent=*/false), - BaseType(T), Protocols(Protos, Protos+NumP) { } - friend class ASTContext; // ASTContext creates these. - -public: - QualType getBaseType() const { return BaseType; } - - /// \brief Provides access to the list of protocols qualifying the base type. - typedef llvm::SmallVector<ObjCProtocolDecl*, 4>::const_iterator qual_iterator; - - qual_iterator qual_begin() const { return Protocols.begin(); } - qual_iterator qual_end() const { return Protocols.end(); } - bool qual_empty() const { return Protocols.size() == 0; } - - /// \brief Return the number of qualifying protocols. - unsigned getNumProtocols() const { return Protocols.size(); } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - 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() == ObjCProtocolList; - } - static bool classof(const ObjCProtocolListType *) { return true; } -}; - /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { ASTContext *Context; @@ -2646,6 +2617,20 @@ public: // Inline function definitions. +inline bool QualType::isCanonical() const { + const Type *T = getTypePtr(); + if (hasQualifiers()) + return T->isCanonicalUnqualified() && !isa<ArrayType>(T); + return T->isCanonicalUnqualified(); +} + +inline bool QualType::isCanonicalAsParam() const { + if (hasQualifiers()) return false; + const Type *T = getTypePtr(); + return T->isCanonicalUnqualified() && + !isa<FunctionType>(T) && !isa<ArrayType>(T); +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 3735eee476298..1d7181b531f8c 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -18,10 +18,15 @@ namespace clang { class ParmVarDecl; - class TypeSpecLoc; class DeclaratorInfo; class UnqualTypeLoc; +// Predeclare all the type nodes. +#define ABSTRACT_TYPELOC(Class, Base) +#define TYPELOC(Class, Base) \ + class Class##TypeLoc; +#include "clang/AST/TypeLocNodes.def" + /// \brief Base wrapper for a particular "section" of type source info. /// /// A client should use the TypeLoc subclasses through cast/dyn_cast in order to @@ -34,12 +39,28 @@ protected: void *Data; public: + /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, + /// except it also defines a Qualified enum that corresponds to the + /// QualifiedLoc class. + enum TypeLocClass { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + Class = Type::Class, +#include "clang/AST/TypeNodes.def" + Qualified + }; + TypeLoc() : Ty(0), Data(0) { } TypeLoc(QualType ty, void *opaqueData) : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } TypeLoc(Type *ty, void *opaqueData) : Ty(ty), Data(opaqueData) { } + TypeLocClass getTypeLocClass() const { + if (getType().hasQualifiers()) return Qualified; + return (TypeLocClass) getType()->getTypeClass(); + } + bool isNull() const { return !Ty; } operator bool() const { return Ty; } @@ -48,35 +69,45 @@ public: /// \brief Get the type for which this source info wrapper provides /// information. - QualType getSourceType() const { return QualType::getFromOpaquePtr(Ty); } + QualType getType() const { + return QualType::getFromOpaquePtr(Ty); + } - Type *getSourceTypePtr() const { + Type *getTypePtr() const { return QualType::getFromOpaquePtr(Ty).getTypePtr(); } /// \brief Get the pointer where source information is stored. - void *getOpaqueData() const { return Data; } - - SourceRange getSourceRange() const; - - /// \brief Find the TypeSpecLoc that is part of this TypeLoc. - TypeSpecLoc getTypeSpecLoc() const; + void *getOpaqueData() const { + return Data; + } - /// \brief Find the TypeSpecLoc that is part of this TypeLoc and return its - /// SourceRange. - SourceRange getTypeSpecRange() const; + SourceRange getSourceRange() const { + return getSourceRangeImpl(*this); + } /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { - return getFullDataSizeForType(getSourceType()); + return getFullDataSizeForType(getType()); } /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the /// TypeLoc is a PointerLoc and next TypeLoc is for "int". - TypeLoc getNextTypeLoc() const; + TypeLoc getNextTypeLoc() const { + return getNextTypeLocImpl(*this); + } /// \brief Skips past any qualifiers, if this is qualified. - UnqualTypeLoc getUnqualifiedLoc() const; + UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header + + /// \brief Initializes this to state that every location in this + /// type is the given location. + /// + /// This method exists to provide a simple transition for code that + /// relies on location-less types. + void initialize(SourceLocation Loc) const { + initializeImpl(*this, Loc); + } friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; @@ -87,6 +118,11 @@ public: } static bool classof(const TypeLoc *TL) { return true; } + +private: + static void initializeImpl(TypeLoc TL, SourceLocation Loc); + static TypeLoc getNextTypeLocImpl(TypeLoc TL); + static SourceRange getSourceRangeImpl(TypeLoc TL); }; /// \brief Wrapper of type source information for a type with @@ -96,12 +132,16 @@ public: UnqualTypeLoc() {} UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {} - Type *getSourceTypePtr() const { + Type *getTypePtr() const { return reinterpret_cast<Type*>(Ty); } + TypeLocClass getTypeLocClass() const { + return (TypeLocClass) getTypePtr()->getTypeClass(); + } + static bool classof(const TypeLoc *TL) { - return !TL->getSourceType().hasQualifiers(); + return !TL->getType().hasQualifiers(); } static bool classof(const UnqualTypeLoc *TL) { return true; } }; @@ -111,14 +151,24 @@ public: /// /// Currently, we intentionally do not provide source location for /// type qualifiers. -class QualifiedLoc : public TypeLoc { +class QualifiedTypeLoc : public TypeLoc { public: SourceRange getSourceRange() const { return SourceRange(); } UnqualTypeLoc getUnqualifiedLoc() const { - return UnqualTypeLoc(getSourceTypePtr(), Data); + return UnqualTypeLoc(getTypePtr(), Data); + } + + /// Initializes the local data of this type source info block to + /// provide no information. + void initializeLocal(SourceLocation Loc) { + // do nothing + } + + TypeLoc getNextTypeLoc() const { + return getUnqualifiedLoc(); } /// \brief Returns the size of the type source info data block that is @@ -132,52 +182,21 @@ public: /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getLocalDataSize() + - getFullDataSizeForType(getSourceType().getUnqualifiedType()); + getFullDataSizeForType(getType().getUnqualifiedType()); } static bool classof(const TypeLoc *TL) { - return TL->getSourceType().hasQualifiers(); + return TL->getType().hasQualifiers(); } - static bool classof(const QualifiedLoc *TL) { return true; } + static bool classof(const QualifiedTypeLoc *TL) { return true; } }; inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { - if (isa<QualifiedLoc>(this)) - return cast<QualifiedLoc>(this)->getUnqualifiedLoc(); + if (isa<QualifiedTypeLoc>(this)) + return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc(); return cast<UnqualTypeLoc>(*this); } -/// \brief Base wrapper of type source info data for type-spec types. -class TypeSpecLoc : public UnqualTypeLoc { -public: - static bool classof(const TypeLoc *TL) { - return (UnqualTypeLoc::classof(TL) && - classof(static_cast<const UnqualTypeLoc*>(TL))); - } - static bool classof(const UnqualTypeLoc *TL); - static bool classof(const TypeSpecLoc *TL) { return true; } -}; - -inline SourceRange TypeLoc::getTypeSpecRange() const { - return getTypeSpecLoc().getSourceRange(); -} - -/// \brief Base wrapper of type source info data for types part of a declarator, -/// excluding type-spec types. -class DeclaratorLoc : public UnqualTypeLoc { -public: - /// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc. - TypeSpecLoc getTypeSpecLoc() const; - - static bool classof(const TypeLoc *TL) { - return (UnqualTypeLoc::classof(TL) && - classof(static_cast<const UnqualTypeLoc*>(TL))); - } - static bool classof(const UnqualTypeLoc *TL); - static bool classof(const DeclaratorLoc *TL) { return true; } -}; - - /// A metaprogramming base class for TypeLoc classes which correspond /// to a particular Type subclass. It is accepted for a single /// TypeLoc class to correspond to multiple Type classes. @@ -196,9 +215,19 @@ public: /// getExtraLocalDataSize(); getExtraLocalData() will then point to /// this extra memory. /// -/// TypeLocs with an inner type should override hasInnerType() and -/// getInnerType(); getInnerTypeLoc() will then point to this inner -/// type's location data. +/// TypeLocs with an inner type should define +/// QualType getInnerType() const +/// and getInnerTypeLoc() will then point to this inner type's +/// location data. +/// +/// A word about hierarchies: this template is not designed to be +/// derived from multiple times in a hierarchy. It is also not +/// designed to be used for classes where subtypes might provide +/// different amounts of source information. It should be subclassed +/// only at the deepest portion of the hierarchy where all children +/// have identical source information; if that's an abstract type, +/// then further descendents should inherit from +/// InheritingConcreteTypeLoc instead. template <class Base, class Derived, class TypeClass, class LocalData> class ConcreteTypeLoc : public Base { @@ -215,25 +244,19 @@ public: return asDerived()->getLocalDataSize() + getInnerTypeSize(); } - static bool classof(const TypeLoc *TL) { - return Derived::classofType(TL->getSourceTypePtr()); - } - static bool classof(const UnqualTypeLoc *TL) { - return Derived::classofType(TL->getSourceTypePtr()); - } - static bool classof(const Derived *TL) { - return true; - } - static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } -protected: + TypeLoc getNextTypeLoc() const { + return getNextTypeLoc(asDerived()->getInnerType()); + } + TypeClass *getTypePtr() const { - return cast<TypeClass>(Base::getSourceTypePtr()); + return cast<TypeClass>(Base::getTypePtr()); } +protected: unsigned getExtraLocalDataSize() const { return 0; } @@ -253,136 +276,151 @@ protected: return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize(); } - bool hasInnerType() const { - return false; - } + struct HasNoInnerType {}; + HasNoInnerType getInnerType() const { return HasNoInnerType(); } TypeLoc getInnerTypeLoc() const { - assert(asDerived()->hasInnerType()); return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); } private: unsigned getInnerTypeSize() const { - if (asDerived()->hasInnerType()) - return getInnerTypeLoc().getFullDataSize(); + return getInnerTypeSize(asDerived()->getInnerType()); + } + + unsigned getInnerTypeSize(HasNoInnerType _) const { return 0; } - // Required here because my metaprogramming is too weak to avoid it. - QualType getInnerType() const { - assert(0 && "getInnerType() not overridden"); - return QualType(); + unsigned getInnerTypeSize(QualType _) const { + return getInnerTypeLoc().getFullDataSize(); } -}; + TypeLoc getNextTypeLoc(HasNoInnerType _) const { + return TypeLoc(); + } -struct DefaultTypeSpecLocInfo { - SourceLocation StartLoc; + TypeLoc getNextTypeLoc(QualType T) const { + return TypeLoc(T, getNonLocalData()); + } }; -/// \brief The default wrapper for type-spec types that are not handled by -/// another specific wrapper. -class DefaultTypeSpecLoc : public ConcreteTypeLoc<TypeSpecLoc, - DefaultTypeSpecLoc, - Type, - DefaultTypeSpecLocInfo> { +/// A metaprogramming class designed for concrete subtypes of abstract +/// types where all subtypes share equivalently-structured source +/// information. See the note on ConcreteTypeLoc. +template <class Base, class Derived, class TypeClass> +class InheritingConcreteTypeLoc : public Base { public: - SourceLocation getStartLoc() const { - return getLocalData()->StartLoc; + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); } - void setStartLoc(SourceLocation Loc) { - getLocalData()->StartLoc = Loc; + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); } - SourceRange getSourceRange() const { - return SourceRange(getStartLoc(), getStartLoc()); + static bool classof(const Derived *TL) { + return true; } - static bool classofType(const Type *T); + TypeClass *getTypePtr() const { + return cast<TypeClass>(Base::getTypePtr()); + } }; - -struct TypedefLocInfo { +struct TypeSpecLocInfo { SourceLocation NameLoc; }; -/// \brief Wrapper for source info for typedefs. -class TypedefLoc : public ConcreteTypeLoc<TypeSpecLoc,TypedefLoc, - TypedefType,TypedefLocInfo> { +/// \brief A reasonable base class for TypeLocs that correspond to +/// types that are written as a type-specifier. +template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo> +class TypeSpecTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { public: SourceLocation getNameLoc() const { - return getLocalData()->NameLoc; + return this->getLocalData()->NameLoc; } void setNameLoc(SourceLocation Loc) { - getLocalData()->NameLoc = Loc; + this->getLocalData()->NameLoc = Loc; } SourceRange getSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } + void initializeLocal(SourceLocation Loc) { + setNameLoc(Loc); + } +}; +/// \brief Wrapper for source info for typedefs. +class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> { +public: TypedefDecl *getTypedefDecl() const { return getTypePtr()->getDecl(); } }; -struct ObjCInterfaceLocInfo { - SourceLocation NameLoc; +/// \brief Wrapper for source info for builtin types. +class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc, + BuiltinType> { }; -/// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceLoc : public ConcreteTypeLoc<TypeSpecLoc, - ObjCInterfaceLoc, - ObjCInterfaceType, - ObjCInterfaceLocInfo> { -public: - SourceLocation getNameLoc() const { - return getLocalData()->NameLoc; - } - void setNameLoc(SourceLocation Loc) { - getLocalData()->NameLoc = Loc; - } - SourceRange getSourceRange() const { - return SourceRange(getNameLoc(), getNameLoc()); - } +/// \brief Wrapper for template type parameters. +class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc, + TemplateTypeParmType> { +}; - ObjCInterfaceDecl *getIFaceDecl() const { - return getTypePtr()->getDecl(); - } +/// \brief Wrapper for substituted template type parameters. +class SubstTemplateTypeParmTypeLoc : + public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc, + SubstTemplateTypeParmType> { }; struct ObjCProtocolListLocInfo { - SourceLocation LAngleLoc, RAngleLoc; + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; }; -/// \brief Wrapper for source info for ObjC protocol lists. -class ObjCProtocolListLoc : public ConcreteTypeLoc<TypeSpecLoc, - ObjCProtocolListLoc, - ObjCProtocolListType, - ObjCProtocolListLocInfo> { +// A helper class for defining ObjC TypeLocs that can qualified with +// protocols. +// +// TypeClass basically has to be either ObjCInterfaceType or +// ObjCObjectPointerType. +template <class Derived, class TypeClass, class LocalData> +class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + Derived, + TypeClass, + LocalData> { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { - return (SourceLocation*) getExtraLocalData(); + return (SourceLocation*) this->getExtraLocalData(); + } + +protected: + void initializeLocalBase(SourceLocation Loc) { + setLAngleLoc(Loc); + setRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); } public: SourceLocation getLAngleLoc() const { - return getLocalData()->LAngleLoc; + return this->getLocalData()->LAngleLoc; } void setLAngleLoc(SourceLocation Loc) { - getLocalData()->LAngleLoc = Loc; + this->getLocalData()->LAngleLoc = Loc; } SourceLocation getRAngleLoc() const { - return getLocalData()->RAngleLoc; + return this->getLocalData()->RAngleLoc; } void setRAngleLoc(SourceLocation Loc) { - getLocalData()->RAngleLoc = Loc; + this->getLocalData()->RAngleLoc = Loc; } unsigned getNumProtocols() const { - return getTypePtr()->getNumProtocols(); + return this->getTypePtr()->getNumProtocols(); } SourceLocation getProtocolLoc(unsigned i) const { @@ -396,165 +434,229 @@ public: ObjCProtocolDecl *getProtocol(unsigned i) const { assert(i < getNumProtocols() && "Index is out of bounds!"); - return *(getTypePtr()->qual_begin() + i); + return *(this->getTypePtr()->qual_begin() + i); } - TypeLoc getBaseTypeLoc() const { - return getInnerTypeLoc(); - } - SourceRange getSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. - unsigned getExtraLocalDataSize() const { - return getNumProtocols() * sizeof(SourceLocation); + void initializeLocal(SourceLocation Loc) { + initializeLocalBase(Loc); } - bool hasInnerType() const { return true; } - QualType getInnerType() const { return getTypePtr()->getBaseType(); } + unsigned getExtraLocalDataSize() const { + return this->getNumProtocols() * sizeof(SourceLocation); + } }; -struct PointerLocInfo { - SourceLocation StarLoc; +struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { + SourceLocation NameLoc; }; -/// \brief Wrapper for source info for pointers. -class PointerLoc : public ConcreteTypeLoc<DeclaratorLoc, - PointerLoc, - PointerType, - PointerLocInfo> { +/// \brief Wrapper for source info for ObjC interfaces. +class ObjCInterfaceTypeLoc : + public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { public: - SourceLocation getStarLoc() const { - return getLocalData()->StarLoc; - } - void setStarLoc(SourceLocation Loc) { - getLocalData()->StarLoc = Loc; + ObjCInterfaceDecl *getIFaceDecl() const { + return getTypePtr()->getDecl(); } - TypeLoc getPointeeLoc() const { - return getInnerTypeLoc(); + SourceLocation getNameLoc() const { + return getLocalData()->NameLoc; } - /// \brief Find the TypeSpecLoc that is part of this PointerLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getPointeeLoc().getTypeSpecLoc(); + void setNameLoc(SourceLocation Loc) { + getLocalData()->NameLoc = Loc; } SourceRange getSourceRange() const { - return SourceRange(getStarLoc(), getStarLoc()); + if (getNumProtocols()) + return SourceRange(getNameLoc(), getRAngleLoc()); + else + return SourceRange(getNameLoc(), getNameLoc()); } - bool hasInnerType() const { return true; } - QualType getInnerType() const { return getTypePtr()->getPointeeType(); } + void initializeLocal(SourceLocation Loc) { + initializeLocalBase(Loc); + setNameLoc(Loc); + } }; -struct BlockPointerLocInfo { - SourceLocation CaretLoc; +struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { + SourceLocation StarLoc; + bool HasProtocols; + bool HasBaseType; }; -/// \brief Wrapper for source info for block pointers. -class BlockPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, - BlockPointerLoc, - BlockPointerType, - BlockPointerLocInfo> { +/// Wraps an ObjCPointerType with source location information. Note +/// that not all ObjCPointerTypes actually have a star location; nor +/// are protocol locations necessarily written in the source just +/// because they're present on the type. +class ObjCObjectPointerTypeLoc : + public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc, + ObjCObjectPointerType, + ObjCObjectPointerLocInfo> { public: - SourceLocation getCaretLoc() const { - return getLocalData()->CaretLoc; + bool hasProtocolsAsWritten() const { + return getLocalData()->HasProtocols; } - void setCaretLoc(SourceLocation Loc) { - getLocalData()->CaretLoc = Loc; + + void setHasProtocolsAsWritten(bool HasProtocols) { + getLocalData()->HasProtocols = HasProtocols; } - TypeLoc getPointeeLoc() const { - return getInnerTypeLoc(); + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseType; } - /// \brief Find the TypeSpecLoc that is part of this BlockPointerLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getPointeeLoc().getTypeSpecLoc(); + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseType = HasBaseType; + } + + SourceLocation getStarLoc() const { + return getLocalData()->StarLoc; + } + + void setStarLoc(SourceLocation Loc) { + getLocalData()->StarLoc = Loc; } SourceRange getSourceRange() const { - return SourceRange(getCaretLoc(), getCaretLoc()); + // Being written with protocols is incompatible with being written + // with a star. + if (hasProtocolsAsWritten()) + return SourceRange(getLAngleLoc(), getRAngleLoc()); + else + return SourceRange(getStarLoc(), getStarLoc()); + } + + void initializeLocal(SourceLocation Loc) { + initializeLocalBase(Loc); + setHasProtocolsAsWritten(false); + setHasBaseTypeAsWritten(false); + setStarLoc(Loc); + } + + TypeLoc getBaseTypeLoc() const { + return getInnerTypeLoc(); } - bool hasInnerType() const { return true; } - QualType getInnerType() const { return getTypePtr()->getPointeeType(); } + QualType getInnerType() const { + return getTypePtr()->getPointeeType(); + } }; -struct MemberPointerLocInfo { +struct PointerLikeLocInfo { SourceLocation StarLoc; }; -/// \brief Wrapper for source info for member pointers. -class MemberPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, - MemberPointerLoc, - MemberPointerType, - MemberPointerLocInfo> { -public: - SourceLocation getStarLoc() const { - return getLocalData()->StarLoc; +/// A base class for +template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> +class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, + TypeClass, LocalData> { +public: + SourceLocation getSigilLoc() const { + return this->getLocalData()->StarLoc; } - void setStarLoc(SourceLocation Loc) { - getLocalData()->StarLoc = Loc; + void setSigilLoc(SourceLocation Loc) { + this->getLocalData()->StarLoc = Loc; } TypeLoc getPointeeLoc() const { - return getInnerTypeLoc(); + return this->getInnerTypeLoc(); } - /// \brief Find the TypeSpecLoc that is part of this MemberPointerLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getPointeeLoc().getTypeSpecLoc(); + SourceRange getSourceRange() const { + return SourceRange(getSigilLoc(), getSigilLoc()); } - SourceRange getSourceRange() const { - return SourceRange(getStarLoc(), getStarLoc()); + void initializeLocal(SourceLocation Loc) { + setSigilLoc(Loc); } - bool hasInnerType() const { return true; } - QualType getInnerType() const { return getTypePtr()->getPointeeType(); } + QualType getInnerType() const { + return this->getTypePtr()->getPointeeType(); + } }; -struct ReferenceLocInfo { - SourceLocation AmpLoc; +/// \brief Wrapper for source info for pointers. +class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, + PointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } }; -/// \brief Wrapper for source info for references. -class ReferenceLoc : public ConcreteTypeLoc<DeclaratorLoc, - ReferenceLoc, - ReferenceType, - ReferenceLocInfo> { + +/// \brief Wrapper for source info for block pointers. +class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, + BlockPointerType> { public: - SourceLocation getAmpLoc() const { - return getLocalData()->AmpLoc; + SourceLocation getCaretLoc() const { + return getSigilLoc(); } - void setAmpLoc(SourceLocation Loc) { - getLocalData()->AmpLoc = Loc; + void setCaretLoc(SourceLocation Loc) { + setSigilLoc(Loc); } +}; - TypeLoc getPointeeLoc() const { - return TypeLoc(getTypePtr()->getPointeeType(), getNonLocalData()); + +/// \brief Wrapper for source info for member pointers. +class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, + MemberPointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); } +}; - /// \brief Find the TypeSpecLoc that is part of this ReferenceLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getPointeeLoc().getTypeSpecLoc(); + +class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, + ReferenceType> { +public: + QualType getInnerType() const { + return getTypePtr()->getPointeeTypeAsWritten(); } +}; - SourceRange getSourceRange() const { - return SourceRange(getAmpLoc(), getAmpLoc()); +class LValueReferenceTypeLoc : + public InheritingConcreteTypeLoc<ReferenceTypeLoc, + LValueReferenceTypeLoc, + LValueReferenceType> { +public: + SourceLocation getAmpLoc() const { + return getSigilLoc(); + } + void setAmpLoc(SourceLocation Loc) { + setSigilLoc(Loc); } +}; - bool hasInnerType() const { return true; } - QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +class RValueReferenceTypeLoc : + public InheritingConcreteTypeLoc<ReferenceTypeLoc, + RValueReferenceTypeLoc, + RValueReferenceType> { +public: + SourceLocation getAmpAmpLoc() const { + return getSigilLoc(); + } + void setAmpAmpLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } }; @@ -563,10 +665,10 @@ struct FunctionLocInfo { }; /// \brief Wrapper for source info for functions. -class FunctionLoc : public ConcreteTypeLoc<DeclaratorLoc, - FunctionLoc, - FunctionType, - FunctionLocInfo> { +class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + FunctionTypeLoc, + FunctionType, + FunctionLocInfo> { // ParmVarDecls* are stored after Info, one for each argument. ParmVarDecl **getParmArray() const { return (ParmVarDecl**) getExtraLocalData(); @@ -601,24 +703,38 @@ public: return getInnerTypeLoc(); } - /// \brief Find the TypeSpecLoc that is part of this FunctionLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getResultLoc().getTypeSpecLoc(); - } SourceRange getSourceRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } + void initializeLocal(SourceLocation Loc) { + setLParenLoc(Loc); + setRParenLoc(Loc); + for (unsigned i = 0, e = getNumArgs(); i != e; ++i) + setArg(i, NULL); + } + /// \brief Returns the size of the type source info data block that is /// specific to this type. unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(ParmVarDecl*); } - bool hasInnerType() const { return true; } QualType getInnerType() const { return getTypePtr()->getResultType(); } }; +class FunctionProtoTypeLoc : + public InheritingConcreteTypeLoc<FunctionTypeLoc, + FunctionProtoTypeLoc, + FunctionProtoType> { +}; + +class FunctionNoProtoTypeLoc : + public InheritingConcreteTypeLoc<FunctionTypeLoc, + FunctionNoProtoTypeLoc, + FunctionNoProtoType> { +}; + struct ArrayLocInfo { SourceLocation LBracketLoc, RBracketLoc; @@ -626,10 +742,10 @@ struct ArrayLocInfo { }; /// \brief Wrapper for source info for arrays. -class ArrayLoc : public ConcreteTypeLoc<DeclaratorLoc, - ArrayLoc, - ArrayType, - ArrayLocInfo> { +class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ArrayTypeLoc, + ArrayType, + ArrayLocInfo> { public: SourceLocation getLBracketLoc() const { return getLocalData()->LBracketLoc; @@ -656,18 +772,108 @@ public: return getInnerTypeLoc(); } - /// \brief Find the TypeSpecLoc that is part of this ArrayLoc. - TypeSpecLoc getTypeSpecLoc() const { - return getElementLoc().getTypeSpecLoc(); - } SourceRange getSourceRange() const { return SourceRange(getLBracketLoc(), getRBracketLoc()); } - bool hasInnerType() const { return true; } + void initializeLocal(SourceLocation Loc) { + setLBracketLoc(Loc); + setRBracketLoc(Loc); + setSizeExpr(NULL); + } + QualType getInnerType() const { return getTypePtr()->getElementType(); } }; +class ConstantArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + ConstantArrayTypeLoc, + ConstantArrayType> { +}; + +class IncompleteArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + IncompleteArrayTypeLoc, + IncompleteArrayType> { +}; + +class DependentSizedArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + DependentSizedArrayTypeLoc, + DependentSizedArrayType> { + +}; + +class VariableArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + VariableArrayTypeLoc, + VariableArrayType> { +}; + +// None of these types have proper implementations yet. + +class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> { +}; + +class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, + ExtVectorTypeLoc, + ExtVectorType> { +}; + +// For some reason, this isn't a subtype of VectorType. +class DependentSizedExtVectorTypeLoc : + public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc, + DependentSizedExtVectorType> { +}; + +class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc, + FixedWidthIntType> { +}; + +class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc, + ComplexType> { +}; + +class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc, + TypeOfExprType> { +}; + +class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> { +}; + +class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> { +}; + +class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> { +}; + +class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + RecordTypeLoc, + RecordType> { +}; + +class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + EnumTypeLoc, + EnumType> { +}; + +class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc, + ElaboratedType> { +}; + +class TemplateSpecializationTypeLoc + : public TypeSpecTypeLoc<TemplateSpecializationTypeLoc, + TemplateSpecializationType> { +}; + +class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc, + QualifiedNameType> { +}; + +class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc, + TypenameType> { +}; + } #endif diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h new file mode 100644 index 0000000000000..4e1fbaaf4c5ed --- /dev/null +++ b/include/clang/AST/TypeLocBuilder.h @@ -0,0 +1,122 @@ +//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H +#define LLVM_CLANG_AST_TYPELOCBUILDER_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class TypeLocBuilder { + enum { InlineCapacity = 8 * sizeof(SourceLocation) }; + + /// The underlying location-data buffer. Data grows from the end + /// of the buffer backwards. + char *Buffer; + + /// The capacity of the current buffer. + size_t Capacity; + + /// The index of the first occupied byte in the buffer. + size_t Index; + +#ifndef NDEBUG + /// The last type pushed on this builder. + QualType LastTy; +#endif + + /// The inline buffer. + char InlineBuffer[InlineCapacity]; + + public: + TypeLocBuilder() + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) + {} + + ~TypeLocBuilder() { + if (Buffer != InlineBuffer) + delete[] Buffer; + } + + /// Ensures that this buffer has at least as much capacity as described. + void reserve(size_t Requested) { + if (Requested > Capacity) + // For now, match the request exactly. + grow(Requested); + } + + /// Pushes space for a new TypeLoc onto the given type. Invalidates + /// any TypeLocs previously retrieved from this builder. + template <class TyLocType> TyLocType push(QualType T) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + Index -= LocalSize; + + return cast<TyLocType>(TypeLoc(T, &Buffer[Index])); + } + + /// Creates a DeclaratorInfo for the given type. + DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + + private: + /// Grow to the given capacity. + void grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; + } +}; + +} + +#endif diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index ecf7cc5c29958..4590e489e3f74 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -7,54 +7,32 @@ // //===----------------------------------------------------------------------===// // -// This file defines the TypeLoc info database. Each node is -// enumerated by providing its name (e.g., "PointerLoc" or "ArrayLoc"), -// base class (e.g., "TypeSpecLoc" or "DeclaratorLoc"), and the Type subclass -// that the TypeLoc is associated with. +// This file defines the TypeLoc info database. Each node is +// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc") +// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc +// are associated // -// TYPELOC(Class, Base) - A TypeLoc subclass. +// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is +// provided, there will be exactly one of these, Qualified. // // UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass. // // ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc. // -// TYPESPEC_TYPELOC(Class, Type) - A TypeLoc referring to a type-spec type. -// -// DECLARATOR_TYPELOC(Class, Type) - A TypeLoc referring to a type part of -// a declarator, excluding type-spec types. -// //===----------------------------------------------------------------------===// #ifndef UNQUAL_TYPELOC -# define UNQUAL_TYPELOC(Class, Base, Type) TYPELOC(Class, Base) +# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base) #endif #ifndef ABSTRACT_TYPELOC -# define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc) -#endif - -#ifndef TYPESPEC_TYPELOC -# define TYPESPEC_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, TypeSpecLoc, Type) +# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base) #endif -#ifndef DECLARATOR_TYPELOC -# define DECLARATOR_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, DeclaratorLoc, Type) -#endif - -TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type) -TYPESPEC_TYPELOC(TypedefLoc, TypedefType) -TYPESPEC_TYPELOC(ObjCInterfaceLoc, ObjCInterfaceType) -TYPESPEC_TYPELOC(ObjCProtocolListLoc, ObjCProtocolListType) -DECLARATOR_TYPELOC(PointerLoc, PointerType) -DECLARATOR_TYPELOC(BlockPointerLoc, BlockPointerType) -DECLARATOR_TYPELOC(MemberPointerLoc, MemberPointerType) -DECLARATOR_TYPELOC(ReferenceLoc, ReferenceType) -DECLARATOR_TYPELOC(FunctionLoc, FunctionType) -DECLARATOR_TYPELOC(ArrayLoc, ArrayType) -ABSTRACT_TYPELOC(DeclaratorLoc) -ABSTRACT_TYPELOC(TypeSpecLoc) -TYPELOC(QualifiedLoc, TypeLoc) - +TYPELOC(Qualified, TypeLoc) +#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc) +#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc) +#include "clang/AST/TypeNodes.def" #undef DECLARATOR_TYPELOC #undef TYPESPEC_TYPELOC diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index a96757f123e87..a62bb3f853bc1 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -15,46 +15,38 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeVisitor.h" +#include "llvm/Support/ErrorHandling.h" namespace clang { -#define DISPATCH(CLASS) \ - return static_cast<ImplClass*>(this)->Visit ## CLASS(cast<CLASS>(TyLoc)) +#define DISPATCH(CLASSNAME) \ + return static_cast<ImplClass*>(this)-> \ + Visit##CLASSNAME(cast<CLASSNAME>(TyLoc)) template<typename ImplClass, typename RetTy=void> class TypeLocVisitor { - class TypeDispatch : public TypeVisitor<TypeDispatch, RetTy> { - ImplClass *Impl; - UnqualTypeLoc TyLoc; - - public: - TypeDispatch(ImplClass *impl, UnqualTypeLoc &tyLoc) - : Impl(impl), TyLoc(tyLoc) { } -#define TYPELOC(CLASS, BASE) -#define ABSTRACT_TYPELOC(CLASS) -#define UNQUAL_TYPELOC(CLASS, PARENT, TYPE) \ - RetTy Visit##TYPE(TYPE *) { \ - return Impl->Visit##CLASS(reinterpret_cast<CLASS&>(TyLoc)); \ - } -#include "clang/AST/TypeLocNodes.def" - }; - public: RetTy Visit(TypeLoc TyLoc) { - if (isa<QualifiedLoc>(TyLoc)) - return static_cast<ImplClass*>(this)-> - VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc)); - - return Visit(cast<UnqualTypeLoc>(TyLoc)); + switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" + } + llvm::llvm_unreachable("unexpected type loc class!"); } RetTy Visit(UnqualTypeLoc TyLoc) { - TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc); - return TD.Visit(TyLoc.getSourceTypePtr()); + switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" + } } #define TYPELOC(CLASS, PARENT) \ - RetTy Visit##CLASS(CLASS TyLoc) { \ + RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ DISPATCH(PARENT); \ } #include "clang/AST/TypeLocNodes.def" diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 6c6bd20e85283..c2721236af02b 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -62,8 +62,6 @@ TYPE(RValueReference, ReferenceType) TYPE(MemberPointer, Type) ABSTRACT_TYPE(Array, Type) TYPE(ConstantArray, ArrayType) -NON_CANONICAL_TYPE(ConstantArrayWithExpr, ConstantArrayType) -NON_CANONICAL_TYPE(ConstantArrayWithoutExpr, ConstantArrayType) TYPE(IncompleteArray, ArrayType) TYPE(VariableArray, ArrayType) DEPENDENT_TYPE(DependentSizedArray, ArrayType) @@ -82,12 +80,12 @@ TYPE(Record, TagType) TYPE(Enum, TagType) NON_CANONICAL_TYPE(Elaborated, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) +NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) -NON_CANONICAL_TYPE(ObjCProtocolList, Type) // These types are always leaves in the type hierarchy. #ifdef LEAF_TYPE @@ -95,7 +93,6 @@ LEAF_TYPE(Enum) LEAF_TYPE(Builtin) LEAF_TYPE(FixedWidthInt) LEAF_TYPE(ObjCInterface) -LEAF_TYPE(ObjCObjectPointer) LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE #endif |