diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-23 14:22:18 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-23 14:22:18 +0000 |
commit | 73490b890977362d28dd6326843a1ecae413921d (patch) | |
tree | 3fdd91eae574e32453a4baf462961c742df2691a /include | |
parent | a5f348eb914e67b51914117fac117c18c1f8d650 (diff) |
Update clang to r84949.vendor/clang/clang-r84949
Notes
Notes:
svn path=/vendor/clang/dist/; revision=198398
svn path=/vendor/clang/clang-r84949/; revision=198399; tag=vendor/clang/clang-r84949
Diffstat (limited to 'include')
35 files changed, 1303 insertions, 665 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 3178017e45be..44cbe0efff81 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -99,18 +99,84 @@ typedef struct { } CXCursor; /* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */ -typedef void *CXEntity; +typedef void *CXEntity; -CXIndex clang_createIndex(); +/** + * \brief clang_createIndex() provides a shared context for creating + * translation units. It provides two options: + * + * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" + * declarations (when loading any new translation units). A "local" declaration + * is one that belongs in the translation unit itself and not in a precompiled + * header that was used by the translation unit. If zero, all declarations + * will be enumerated. + * + * - displayDiagnostics: when non-zero, diagnostics will be output. If zero, + * diagnostics will be ignored. + * + * Here is an example: + * + * // excludeDeclsFromPCH = 1, displayDiagnostics = 1 + * Idx = clang_createIndex(1, 1); + * + * // IndexTest.pch was produced with the following command: + * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" + * TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); + * + * // This will load all the symbols from 'IndexTest.pch' + * clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * // This will load all the symbols from 'IndexTest.c', excluding symbols + * // from 'IndexTest.pch'. + * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch", 0 }; + * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args); + * clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * This process of creating the 'pch', loading it separately, and using it (via + * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks + * (which gives the indexer the same performance benefit as the compiler). + */ +CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics); void clang_disposeIndex(CXIndex); const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); +/* + * \brief Create a translation unit from an AST file (-emit-ast). + */ CXTranslationUnit clang_createTranslationUnit( CXIndex, const char *ast_filename ); +/** + * \brief Destroy the specified CXTranslationUnit object. + */ void clang_disposeTranslationUnit(CXTranslationUnit); +/** + * \brief Return the CXTranslationUnit for a given source file and the provided + * command line arguments one would pass to the compiler. + * + * Note: The 'source_filename' argument is optional. If the caller provides a NULL pointer, + * the name of the source file is expected to reside in the specified command line arguments. + * + * Note: When encountered in 'clang_command_line_args', the following options are ignored: + * + * '-c' + * '-emit-ast' + * '-fsyntax-only' + * '-o <output file>' (both '-o' and '<output file>' are ignored) + * + */ +CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, + const char *source_filename /* specify NULL if the source file is in clang_command_line_args */, + int num_clang_command_line_args, + const char **clang_command_line_args +); + /* Usage: clang_loadTranslationUnit(). Will load the toplevel declarations within a translation unit, issuing a 'callback' for each one. @@ -182,9 +248,28 @@ const char *clang_getDeclSource(CXDecl); /* * CXCursor Operations. */ +/** + Usage: clang_getCursor() will translate a source/line/column position + into an AST cursor (to derive semantic information from the source code). + */ CXCursor clang_getCursor(CXTranslationUnit, const char *source_name, unsigned line, unsigned column); +/** + Usage: clang_getCursorWithHint() provides the same functionality as + clang_getCursor() except that it takes an option 'hint' argument. + The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by + the caller) that should be initialized with clang_initCXLookupHint(). + + FIXME: Add a better comment once getCursorWithHint() has more functionality. + */ +typedef CXCursor CXLookupHint; +CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name, + unsigned line, unsigned column, + CXLookupHint *hint); + +void clang_initCXLookupHint(CXLookupHint *hint); + enum CXCursorKind clang_getCursorKind(CXCursor); unsigned clang_isDeclaration(enum CXCursorKind); unsigned clang_isReference(enum CXCursorKind); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 106d568c9b24..30896c91a143 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 6a5e3666a92c..f7a47364a7f6 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 a57bcc184a93..7c826fe75d11 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 d7ac76dd32e4..8b84bc267997 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 f21541c3e710..72ce0d852cfc 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 9e88871565f1..10db7030db18 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 2b12bb5c1b6d..729a2f138303 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 d5dff5065d49..0d09ea325c31 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 89776b91fe4a..db02a68a984d 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 3735eee47629..1d7181b531f8 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 000000000000..4e1fbaaf4c5e --- /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 ecf7cc5c2995..4590e489e3f7 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 a96757f123e8..a62bb3f853bc 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 6c6bd20e8528..c2721236af02 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 diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index ffe282d3caa3..8e02ccf38209 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -60,6 +60,9 @@ public: ~AnalysisContextManager(); AnalysisContext *getContext(const Decl *D); + + // Discard all previously created AnalysisContexts. + void clear(); }; class LocationContext : public llvm::FoldingSetNode { @@ -155,12 +158,17 @@ class LocationContextManager { llvm::FoldingSet<LocationContext> Contexts; public: + ~LocationContextManager(); + StackFrameContext *getStackFrame(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s); ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s); + + /// Discard all previously created LocationContext objects. + void clear(); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index e97f80576a8b..1a64f56ee8a4 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -65,6 +65,11 @@ public: AScope(ScopeDecl), DisplayedFunction(!displayProgress), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), EagerlyAssume(eager), TrimGraph(trim) {} + + void ClearContexts() { + LocCtxMgr.clear(); + AnaCtxMgr.clear(); + } StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 3ff253d0abf3..7a462c579f9f 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -141,9 +141,12 @@ public: const VarDecl *VD, const LocationContext *LC) = 0; + typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; + virtual const GRState *InvalidateRegion(const GRState *state, const MemRegion *R, - const Expr *E, unsigned Count) = 0; + const Expr *E, unsigned Count, + InvalidatedSymbols *IS) = 0; // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index a5e11a100665..b23a80ed481a 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -27,16 +27,16 @@ namespace clang { class BumpVectorContext { - llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1, bool> Alloc; + llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc; public: /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator /// and destroys it when the BumpVectorContext object is destroyed. - BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), true) {} + BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {} /// Construct a new BumpVectorContext that reuses an existing /// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the /// BumpVectorContext object is destroyed. - BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, false) {} + BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {} ~BumpVectorContext() { if (Alloc.getInt()) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 380192e9dae6..005aab3fa6a1 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_DIAGNOSTIC_H #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/type_traits.h" #include <string> #include <vector> @@ -43,7 +44,7 @@ namespace clang { DIAG_START_PARSE = DIAG_START_LEX + 300, DIAG_START_AST = DIAG_START_PARSE + 300, DIAG_START_SEMA = DIAG_START_AST + 100, - DIAG_START_ANALYSIS = DIAG_START_SEMA + 1000, + DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100, DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; @@ -107,7 +108,7 @@ public: /// \brief Create a code modification hint that inserts the given /// code string at a specific location. static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, - const std::string &Code) { + llvm::StringRef Code) { CodeModificationHint Hint; Hint.InsertionLoc = InsertionLoc; Hint.CodeToInsert = Code; @@ -125,7 +126,7 @@ public: /// \brief Create a code modification hint that replaces the given /// source range with the given code string. static CodeModificationHint CreateReplacement(SourceRange RemoveRange, - const std::string &Code) { + llvm::StringRef Code) { CodeModificationHint Hint; Hint.RemoveRange = RemoveRange; Hint.InsertionLoc = RemoveRange.getBegin(); @@ -163,6 +164,10 @@ public: ak_nestednamespec, // NestedNameSpecifier * ak_declcontext // DeclContext * }; + + /// ArgumentValue - This typedef represents on argument value, which is a + /// union discriminated by ArgumentKind, with a value. + typedef std::pair<ArgumentKind, intptr_t> ArgumentValue; private: unsigned char AllExtensionsSilenced; // Used by __extension__ @@ -202,10 +207,17 @@ private: /// ArgToStringFn - A function pointer that converts an opaque diagnostic /// argument to a strings. This takes the modifiers and argument that was /// present in the diagnostic. + /// + /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous + /// arguments formatted for this diagnostic. Implementations of this function + /// can use this information to avoid redundancy across arguments. + /// /// This is a hack to avoid a layering violation between libbasic and libsema. typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModifierLen, const char *Argument, unsigned ArgumentLen, + const ArgumentValue *PrevArgs, + unsigned NumPrevArgs, llvm::SmallVectorImpl<char> &Output, void *Cookie); void *ArgToStringCookie; @@ -310,9 +322,10 @@ public: void ConvertArgToString(ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, + const ArgumentValue *PrevArgs, unsigned NumPrevArgs, llvm::SmallVectorImpl<char> &Output) const { - ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output, - ArgToStringCookie); + ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, + PrevArgs, NumPrevArgs, Output, ArgToStringCookie); } void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { @@ -546,7 +559,7 @@ public: /// return Diag(...); operator bool() const { return true; } - void AddString(const std::string &S) const { + void AddString(llvm::StringRef S) const { assert(NumArgs < Diagnostic::MaxArguments && "Too many arguments to diagnostic!"); if (DiagObj) { @@ -581,7 +594,7 @@ public: }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const std::string &S) { + llvm::StringRef S) { DB.AddString(S); return DB; } diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 6971df50cb55..19b0ea3932a5 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -201,6 +201,9 @@ def warn_expected_implementation : Warning< "@end must appear in an @implementation context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; +def warn_semicolon_before_method_nody : Warning< + "semicolon before method body is ignored">, + InGroup<DiagGroup<"semicolon-before-method-body">>; def err_expected_field_designator : Error< "expected a field designator, such as '.field = 4'">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b1222a3f84eb..7a87e244f77c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -383,6 +383,8 @@ def note_ambig_member_ref_object_type : Note< "lookup in the object type %0 refers here">; def note_ambig_member_ref_scope : Note< "lookup from the current scope refers here">; +def err_qualified_member_nonclass : Error< + "qualified member access refers to a member in %0">; // C++ class members def err_storageclass_invalid_for_member : Error< @@ -785,9 +787,9 @@ def err_ovl_template_candidate : Note< def err_ovl_candidate_deleted : Note< "candidate function has been explicitly %select{made unavailable|deleted}0">; def err_ovl_builtin_binary_candidate : Note< - "built-in candidate operator %0 (%1, %2)">; + "built-in candidate %0">; def err_ovl_builtin_unary_candidate : Note< - "built-in candidate operator %0 (%1)">; + "built-in candidate %0">; def err_ovl_no_viable_function_in_init : Error< "no matching constructor for initialization of %0">; def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; @@ -1112,7 +1114,17 @@ def err_explicit_instantiation_without_qualified_id_quals : Error< "qualifier in explicit instantiation of '%0%1' requires a template-id">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< "explicit instantiation of %q0 must occur in %1">; - +def err_explicit_instantiation_undefined_member : Error< + "explicit instantiation of undefined %select{member class|member function|" + "static data member}0 %1 of class template %2">; +def err_explicit_instantiation_undefined_func_template : Error< + "explicit instantiation of undefined function template %0">; +def err_explicit_instantiation_declaration_after_definition : Error< + "explicit instantiation declaration (with 'extern') follows explicit " + "instantiation definition (without 'extern')">; +def note_explicit_instantiation_definition_here : Note< + "explicit instantiation definition is here">; + // C++ typename-specifiers def err_typename_nested_not_found : Error<"no type named %0 in %1">; def err_typename_nested_not_type : Error< @@ -1734,7 +1746,9 @@ def err_not_tag_in_scope : Error< def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; - +def err_incomplete_object_call : Error< + "incomplete type in call to object of type %0">; + def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, InGroup<Parentheses>; @@ -2156,6 +2170,8 @@ def err_break_not_in_loop_or_switch : Error< def err_default_not_in_switch : Error< "'default' statement not in switch statement">; def err_case_not_in_switch : Error<"'case' statement not in switch statement">; +def warn_bool_switch_condition : Warning< + "switch condition is a bool">; def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">; def err_duplicate_case : Error<"duplicate case value '%0'">; @@ -2187,7 +2203,7 @@ def ext_return_has_expr : ExtWarn< def ext_return_has_void_expr : Extension< "void %select{function|method}1 %0 should not return void expression">; def warn_noreturn_function_has_return_expr : Warning< - "function %0 declared 'noreturn' should not return">, DefaultError, + "function %0 declared 'noreturn' should not return">, InGroup<DiagGroup<"invalid-noreturn">>; def warn_falloff_noreturn_function : Warning< "function declared 'noreturn' should not return">, diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 7c9113c497ef..5e7ac4f3c859 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -71,16 +71,38 @@ public: } }; -// FIXME: This is a lightweight shim that is used by FileManager to cache -// 'stat' system calls. We will use it with PTH to identify if caching -// stat calls in PTH files is a performance win. +/// \brief Abstract interface for introducing a FileManager cache for 'stat' +/// system calls, which is used by precompiled and pretokenized headers to +/// improve performance. class StatSysCallCache { +protected: + llvm::OwningPtr<StatSysCallCache> NextStatCache; + public: virtual ~StatSysCallCache() {} - virtual int stat(const char *path, struct stat *buf) = 0; + virtual int stat(const char *path, struct stat *buf) { + if (getNextStatCache()) + return getNextStatCache()->stat(path, buf); + + return ::stat(path, buf); + } + + /// \brief Sets the next stat call cache in the chain of stat caches. + /// Takes ownership of the given stat cache. + void setNextStatCache(StatSysCallCache *Cache) { + NextStatCache.reset(Cache); + } + + /// \brief Retrieve the next stat call cache in the chain. + StatSysCallCache *getNextStatCache() { return NextStatCache.get(); } + + /// \brief Retrieve the next stat call cache in the chain, transferring + /// ownership of this cache (and, transitively, all of the remaining caches) + /// to the caller. + StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); } }; -/// \brief A stat listener that can be used by FileManager to keep +/// \brief A stat "cache" that can be used by FileManager to keep /// track of the results of stat() calls that occur throughout the /// execution of the front end. class MemorizeStatCalls : public StatSysCallCache { @@ -144,13 +166,22 @@ public: FileManager(); ~FileManager(); - /// setStatCache - Installs the provided StatSysCallCache object within - /// the FileManager. Ownership of this object is transferred to the - /// FileManager. - void setStatCache(StatSysCallCache *statCache) { - StatCache.reset(statCache); - } - + /// \brief Installs the provided StatSysCallCache object within + /// the FileManager. + /// + /// Ownership of this object is transferred to the FileManager. + /// + /// \param statCache the new stat cache to install. Ownership of this + /// object is transferred to the FileManager. + /// + /// \param AtBeginning whether this new stat cache must be installed at the + /// beginning of the chain of stat caches. Otherwise, it will be added to + /// the end of the chain. + void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false); + + /// \brief Removes the provided StatSysCallCache object from the file manager. + void removeStatCache(StatSysCallCache *statCache); + /// getDirectory - Lookup, cache, and verify the specified directory. This /// returns null if the directory doesn't exist. /// diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 84c2fc910d11..e06dfbb2cf1b 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -75,13 +75,13 @@ public: /// This is intended to be used for string literals only: II->isStr("foo"). template <std::size_t StrLen> bool isStr(const char (&Str)[StrLen]) const { - return getLength() == StrLen-1 && !memcmp(getName(), Str, StrLen-1); + return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1); } - /// getName - Return the actual string for this identifier. The returned - /// string is properly null terminated. + /// getNameStart - Return the beginning of the actual string for this + /// identifier. The returned string is properly null terminated. /// - const char *getName() const { + const char *getNameStart() const { if (Entry) return Entry->getKeyData(); // FIXME: This is gross. It would be best not to embed specific details // of the PTH file format here. @@ -101,8 +101,12 @@ public: // std::pair<IdentifierInfo, const char*>, where internal pointer // points to the external string data. const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2; - return (((unsigned) p[0]) - | (((unsigned) p[1]) << 8)) - 1; + return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; + } + + /// getName - Return the actual identifier string. + llvm::StringRef getName() const { + return llvm::StringRef(getNameStart(), getLength()); } /// hasMacroDefinition - Return true if this identifier is #defined to some @@ -232,6 +236,8 @@ public: /// Unlike the version in IdentifierTable, this returns a pointer instead /// of a reference. If the pointer is NULL then the IdentifierInfo cannot /// be found. + // + // FIXME: Move to StringRef API. virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0; }; @@ -333,8 +339,11 @@ public: return *II; } + IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) { + return CreateIdentifierInfo(Name.begin(), Name.end()); + } - IdentifierInfo &get(const llvm::StringRef& Name) { + IdentifierInfo &get(llvm::StringRef Name) { return get(Name.begin(), Name.end()); } @@ -463,7 +472,7 @@ public: const IdentifierInfo *Name) { llvm::SmallString<100> SelectorName; SelectorName = "set"; - SelectorName.append(Name->getName(), Name->getName()+Name->getLength()); + SelectorName += Name->getName(); SelectorName[3] = toupper(SelectorName[3]); IdentifierInfo *SetterName = &Idents.get(SelectorName.data(), diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 65245167d8d5..2184bf3c457c 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -25,27 +25,6 @@ namespace clang { -// Bernstein hash function: -// This is basically copy-and-paste from StringMap. This likely won't -// stay here, which is why I didn't both to expose this function from -// String Map. -inline unsigned BernsteinHash(const char* x) { - unsigned int R = 0; - for ( ; *x != '\0' ; ++x) R = R * 33 + *x; - return R + (R >> 5); -} - -inline unsigned BernsteinHash(const char* x, unsigned n) { - unsigned int R = 0; - for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x; - return R + (R >> 5); -} - -inline unsigned BernsteinHashPartial(const char* x, unsigned n, unsigned R) { - for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x; - return R + (R >> 5); -} - namespace io { typedef uint32_t Offset; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 7eb988f005ec..8a69cba066b3 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -685,26 +685,19 @@ public: /// void PrintStats() const; - // Iteration over the source location entry table. - typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator; - - sloc_entry_iterator sloc_entry_begin() const { - return SLocEntryTable.begin(); - } - - sloc_entry_iterator sloc_entry_end() const { - return SLocEntryTable.end(); - } - unsigned sloc_entry_size() const { return SLocEntryTable.size(); } - const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { - assert(FID.ID < SLocEntryTable.size() && "Invalid id"); + const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { + assert(ID < SLocEntryTable.size() && "Invalid id"); if (ExternalSLocEntries && - FID.ID < SLocEntryLoaded.size() && - !SLocEntryLoaded[FID.ID]) - ExternalSLocEntries->ReadSLocEntry(FID.ID); - return SLocEntryTable[FID.ID]; + ID < SLocEntryLoaded.size() && + !SLocEntryLoaded[ID]) + ExternalSLocEntries->ReadSLocEntry(ID); + return SLocEntryTable[ID]; + } + + const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { + return getSLocEntry(FID.ID); } unsigned getNextOffset() const { return NextOffset; } diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index a1e0a17c882e..b88e2aaba383 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -83,7 +83,7 @@ public: }; protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, - Char16Type, Char32Type, Int64Type; + WIntType, Char16Type, Char32Type, Int64Type; public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } @@ -93,10 +93,20 @@ public: } IntType getIntPtrType() const { return IntPtrType; } IntType getWCharType() const { return WCharType; } + IntType getWIntType() const { return WIntType; } IntType getChar16Type() const { return Char16Type; } IntType getChar32Type() const { return Char32Type; } IntType getInt64Type() const { return Int64Type; } + + /// getTypeWidth - Return the width (in bits) of the specified integer type + /// enum. For example, SignedInt -> getIntWidth(). + unsigned getTypeWidth(IntType T) const; + + /// getTypeSigned - Return whether an integer types is signed. Returns true if + /// the type is signed; false otherwise. + bool getTypeSigned(IntType T) const; + /// getPointerWidth - Return the width of pointers on this target, for the /// specified address space. uint64_t getPointerWidth(unsigned AddrSpace) const { @@ -185,6 +195,10 @@ public: /// For example, SignedShort -> "short". static const char *getTypeName(IntType T); + /// getTypeConstantSuffix - Return the constant suffix for the specified + /// integer type enum. For example, SignedLong -> "L". + static const char *getTypeConstantSuffix(IntType T); + ///===---- Other target property query methods --------------------------===// /// getTargetDefines - Appends the target-specific #define values for this @@ -192,6 +206,7 @@ public: virtual void getTargetDefines(const LangOptions &Opts, std::vector<char> &DefineBuffer) const = 0; + /// getTargetBuiltins - Return information about target-specific builtins for /// the current primary target, and info about which builtins are non-portable /// across the current set of primary and secondary targets. diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 89eb3b8821ca..9573777b5f6f 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -16,6 +16,8 @@ #include "clang/Basic/SourceManager.h" #include "llvm/ADT/OwningPtr.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Basic/FileManager.h" #include <string> namespace clang { @@ -23,6 +25,7 @@ namespace clang { class FileEntry; class SourceManager; class Diagnostic; + class TextDiagnosticBuffer; class HeaderSearch; class TargetInfo; class Preprocessor; @@ -32,18 +35,27 @@ namespace clang { /// \brief Utility class for loading a ASTContext from a PCH file. /// class ASTUnit { - Diagnostic &Diags; + Diagnostic Diags; + FileManager FileMgr; + SourceManager SourceMgr; llvm::OwningPtr<HeaderSearch> HeaderInfo; llvm::OwningPtr<TargetInfo> Target; llvm::OwningPtr<Preprocessor> PP; llvm::OwningPtr<ASTContext> Ctx; - + bool tempFile; + + // OnlyLocalDecls - when true, walking this AST should only visit declarations + // that come from the AST itself, not from included precompiled headers. + // FIXME: This is temporary; eventually, CIndex will always do this. + bool OnlyLocalDecls; + ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT - ASTUnit(Diagnostic &_Diag); + ASTUnit(); public: + ASTUnit(DiagnosticClient *diagClient = NULL); ~ASTUnit(); const SourceManager &getSourceManager() const { return SourceMgr; } @@ -58,14 +70,23 @@ public: const Diagnostic &getDiagnostic() const { return Diags; } Diagnostic &getDiagnostic() { return Diags; } - FileManager &getFileManager(); + const FileManager &getFileManager() const { return FileMgr; } + FileManager &getFileManager() { return FileMgr; } + const std::string &getOriginalSourceFileName(); + const std::string &getPCHFileName(); + void unlinkTemporaryFile() { tempFile = true; } + + bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + /// \brief Create a ASTUnit from a PCH file. /// /// \param Filename - The PCH file to load. /// - /// \param Diags - The Diagnostic implementation to use. + /// \param diagClient - The diagnostics client to use. Specify NULL + /// to use a default client that emits warnings/errors to standard error. + /// The ASTUnit objects takes ownership of this object. /// /// \param FileMgr - The FileManager to use. /// @@ -74,9 +95,10 @@ public: /// /// \returns - The initialized ASTUnit or null if the PCH failed to load. static ASTUnit *LoadFromPCHFile(const std::string &Filename, - Diagnostic &Diags, - FileManager &FileMgr, - std::string *ErrMsg = 0); + std::string *ErrMsg = 0, + DiagnosticClient *diagClient = NULL, + bool OnlyLocalDecls = false, + bool UseBumpAllocator = false); }; } // namespace clang diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 716780e68a52..1e953d671226 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -86,38 +86,33 @@ namespace clang { PREPROCESSOR_BLOCK_ID, /// \brief The block containing the definitions of all of the - /// types used within the PCH file. - TYPES_BLOCK_ID, - - /// \brief The block containing the definitions of all of the - /// declarations stored in the PCH file. - DECLS_BLOCK_ID + /// types and decls used within the PCH file. + DECLTYPES_BLOCK_ID }; /// \brief Record types that occur within the PCH block itself. enum PCHRecordTypes { - /// \brief Offset of each type within the types block. + /// \brief Record code for the offsets of each type. /// /// The TYPE_OFFSET constant describes the record that occurs - /// within the block identified by TYPE_OFFSETS_BLOCK_ID within - /// the PCH file. The record itself is an array of offsets that - /// point into the types block (identified by TYPES_BLOCK_ID in - /// the PCH file). The index into the array is based on the ID + /// within the PCH block. The record itself is an array of offsets that + /// point into the declarations and types block (identified by + /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID /// of a type. For a given type ID @c T, the lower three bits of /// @c T are its qualifiers (const, volatile, restrict), as in /// the QualType class. The upper bits, after being shifted and /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the /// TYPE_OFFSET block to determine the offset of that type's - /// corresponding record within the TYPES_BLOCK_ID block. + /// corresponding record within the DECLTYPES_BLOCK_ID block. TYPE_OFFSET = 1, /// \brief Record code for the offsets of each decl. /// /// The DECL_OFFSET constant describes the record that occurs - /// within the block identifier by DECL_OFFSETS_BLOCK_ID within - /// the PCH file. The record itself is an array of offsets that - /// point into the declarations block (identified by - /// DECLS_BLOCK_ID). The declaration ID is an index into this + /// within the block identified by DECL_OFFSETS_BLOCK_ID within + /// the PCH block. The record itself is an array of offsets that + /// point into the declarations and types block (identified by + /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this /// record, after subtracting one to account for the use of /// declaration ID 0 for a NULL declaration pointer. Index 0 is /// reserved for the translation unit declaration. @@ -353,8 +348,8 @@ namespace clang { /// \brief Record codes for each kind of type. /// - /// These constants describe the records that can occur within a - /// block identified by TYPES_BLOCK_ID in the PCH file. Each + /// These constants describe the type records that can occur within a + /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each /// constant describes a record for a specific type class in the /// AST. enum TypeCode { @@ -402,16 +397,12 @@ namespace clang { TYPE_OBJC_INTERFACE = 21, /// \brief An ObjCObjectPointerType record. TYPE_OBJC_OBJECT_POINTER = 22, - /// \brief An ObjCProtocolListType record. - TYPE_OBJC_PROTOCOL_LIST = 23, /// \brief a DecltypeType record. - TYPE_DECLTYPE = 24, - /// \brief A ConstantArrayWithExprType record. - TYPE_CONSTANT_ARRAY_WITH_EXPR = 25, - /// \brief A ConstantArrayWithoutExprType record. - TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 26, + TYPE_DECLTYPE = 23, /// \brief An ElaboratedType record. - TYPE_ELABORATED = 27 + TYPE_ELABORATED = 24, + /// \brief A SubstTemplateTypeParmType record. + TYPE_SUBST_TEMPLATE_TYPE_PARM = 25 }; /// \brief The type IDs for special types constructed by semantic @@ -443,18 +434,22 @@ namespace clang { /// \brief Objective-C "id" redefinition type SPECIAL_TYPE_OBJC_ID_REDEFINITION = 10, /// \brief Objective-C "Class" redefinition type - SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11 + SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11, + /// \brief Block descriptor type for Blocks CodeGen + SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12, + /// \brief Block extedned descriptor type for Blocks CodeGen + SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13 }; /// \brief Record codes for each kind of declaration. /// - /// These constants describe the records that can occur within a - /// declarations block (identified by DECLS_BLOCK_ID). Each + /// These constants describe the declaration records that can occur within + /// a declarations block (identified by DECLS_BLOCK_ID). Each /// constant describes a record for a specific declaration class /// in the AST. enum DeclCode { /// \brief Attributes attached to a declaration. - DECL_ATTR = 1, + DECL_ATTR = 50, /// \brief A TranslationUnitDecl record. DECL_TRANSLATION_UNIT, /// \brief A TypedefDecl record. @@ -529,14 +524,14 @@ namespace clang { /// \brief Record codes for each kind of statement or expression. /// /// These constants describe the records that describe statements - /// or expressions. These records can occur within either the type - /// or declaration blocks, so they begin with record values of - /// 50. Each constant describes a record for a specific - /// statement or expression class in the AST. + /// or expressions. These records occur within type and declarations + /// block, so they begin with record values of 100. Each constant + /// describes a record for a specific statement or expression class in the + /// AST. enum StmtCode { /// \brief A marker record that indicates that we are at the end /// of an expression. - STMT_STOP = 50, + STMT_STOP = 100, /// \brief A NULL expression. STMT_NULL_PTR, /// \brief A NullStmt record. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 1230e3753e04..cc16970b0040 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -169,6 +169,11 @@ private: /// \brief The AST context into which we'll read the PCH file. ASTContext *Context; + /// \brief The PCH stat cache installed by this PCHReader, if any. + /// + /// The dynamic type of this stat cache is always PCHStatCache + void *StatCache; + /// \brief The AST consumer. ASTConsumer *Consumer; @@ -492,8 +497,8 @@ public: /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". - PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot = 0); + PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, + Diagnostic &Diags, const char *isysroot = 0); ~PCHReader(); /// \brief Load the precompiled header designated by the given file @@ -513,6 +518,9 @@ public: /// \brief Sets and initializes the given Context. void InitializeContext(ASTContext &Context); + /// \brief Retrieve the name of the PCH file + const std::string &getFileName() { return FileName; } + /// \brief Retrieve the name of the original source file name const std::string &getOriginalSourceFile() { return OriginalFileName; } @@ -534,6 +542,10 @@ public: /// comments in the source code. virtual void ReadComments(std::vector<SourceRange> &Comments); + /// \brief Reads a declarator info from the given record. + virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record, + unsigned &Idx); + /// \brief Resolve a type ID into a type, potentially building a new /// type. virtual QualType GetType(pch::TypeID ID); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index a807cd7c4d1f..728e138d9e7c 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -73,6 +73,33 @@ private: /// \brief The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; + /// \brief Stores a declaration or a type to be written to the PCH file. + class DeclOrType { + public: + DeclOrType(Decl *D) : Stored(D), IsType(false) { } + DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { } + + bool isType() const { return IsType; } + bool isDecl() const { return !IsType; } + + QualType getType() const { + assert(isType() && "Not a type!"); + return QualType::getFromOpaquePtr(Stored); + } + + Decl *getDecl() const { + assert(isDecl() && "Not a decl!"); + return static_cast<Decl *>(Stored); + } + + private: + void *Stored; + bool IsType; + }; + + /// \brief The declarations and types to emit. + std::queue<DeclOrType> DeclTypesToEmit; + /// \brief Map that provides the ID numbers of each declaration within /// the output stream. /// @@ -85,10 +112,6 @@ private: /// the declaration's ID. std::vector<uint32_t> DeclOffsets; - /// \brief Queue containing the declarations that we still need to - /// emit. - std::queue<Decl *> DeclsToEmit; - /// \brief Map that provides the ID numbers of each type within the /// output stream. /// @@ -107,10 +130,6 @@ private: /// \brief The type ID that will be assigned to the next new type. pch::TypeID NextTypeID; - /// \brief Queue containing the types that we still need to - /// emit. - std::queue<QualType> TypesToEmit; - /// \brief Map that provides the ID numbers of each identifier in /// the output stream. /// @@ -189,18 +208,17 @@ private: void WritePreprocessor(const Preprocessor &PP); void WriteComments(ASTContext &Context); void WriteType(QualType T); - void WriteTypesBlock(ASTContext &Context); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); - void WriteDeclsBlock(ASTContext &Context); void WriteMethodPool(Sema &SemaRef); void WriteIdentifierTable(Preprocessor &PP); void WriteAttributeRecord(const Attr *Attr); unsigned ParmVarDeclAbbrev; void WriteDeclsBlockAbbrevs(); - + void WriteDecl(ASTContext &Context, Decl *D); + public: /// \brief Create a new precompiled header writer that outputs to /// the given bitstream. @@ -254,6 +272,9 @@ public: /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordData &Record); + /// \brief Emits a reference to a declarator info. + void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record); + /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordData &Record); diff --git a/include/clang/Index/ASTLocation.h b/include/clang/Index/ASTLocation.h index 9620ec5dbd4f..fc18dae1a20c 100644 --- a/include/clang/Index/ASTLocation.h +++ b/include/clang/Index/ASTLocation.h @@ -91,7 +91,7 @@ public: ASTLocation(const Decl *parentDecl, TypeLoc tyLoc) : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) { if (tyLoc) { - Ty.TyPtr = tyLoc.getSourceType().getAsOpaquePtr(); + Ty.TyPtr = tyLoc.getType().getAsOpaquePtr(); Ty.Data = tyLoc.getOpaqueData(); } else ParentDecl.setPointer(0); @@ -124,8 +124,8 @@ public: return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data); } - Decl *dyn_AsDecl() const { return getKind() == N_Decl ? D : 0; } - Stmt *dyn_AsStmt() const { return getKind() == N_Stmt ? Stm : 0; } + Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } + Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; } NamedRef dyn_AsNamedRef() const { return getKind() == N_Type ? AsNamedRef() : NamedRef(); } diff --git a/include/clang/Index/Indexer.h b/include/clang/Index/Indexer.h index 8b1d2dd38bff..361e729feab2 100644 --- a/include/clang/Index/Indexer.h +++ b/include/clang/Index/Indexer.h @@ -14,13 +14,11 @@ #ifndef LLVM_CLANG_INDEX_INDEXER_H #define LLVM_CLANG_INDEX_INDEXER_H -#include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Index/IndexProvider.h" #include "clang/Index/Entity.h" #include "clang/Index/GlobalSelector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/DenseMap.h" -#include "clang/Basic/FileManager.h" #include <map> namespace clang { @@ -39,16 +37,10 @@ public: typedef std::map<GlobalSelector, TUSetTy> SelMapTy; explicit Indexer(Program &prog) : - Prog(prog), Diags(&DiagClient) { } + Prog(prog) { } Program &getProgram() const { return Prog; } - Diagnostic &getDiagnostics() { return Diags; } - const Diagnostic &getDiagnostics() const { return Diags; } - - FileManager &getFileManager() { return FileMgr; } - const FileManager &getFileManager() const { return FileMgr; } - /// \brief Find all Entities and map them to the given translation unit. void IndexAST(TranslationUnit *TU); @@ -59,9 +51,6 @@ public: private: Program &Prog; - TextDiagnosticBuffer DiagClient; - Diagnostic Diags; - FileManager FileMgr; MapTy Map; CtxTUMapTy CtxTUMap; diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h index e78ef8a15563..36cf56dea203 100644 --- a/include/clang/Index/Utils.h +++ b/include/clang/Index/Utils.h @@ -18,7 +18,8 @@ namespace clang { class ASTContext; class SourceLocation; - + class Decl; + namespace idx { class ASTLocation; @@ -26,7 +27,8 @@ namespace idx { /// /// \returns the resolved ASTLocation or an invalid ASTLocation if the source /// location could not be resolved. -ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc); +ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc, + Decl *RelativeToDecl = 0); } // end namespace idx diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 1ee14701fa2d..050b3f42e4cd 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1390,6 +1390,34 @@ public: return ExprEmpty(); } + /// \brief Parsed a C++ destructor reference that refers to a type. + /// + /// This action is used when parsing a destructor reference that uses a + /// template-id, e.g., + /// + /// \code + /// t->~Tmpl<T1, T2> + /// \endcode + /// + /// \param S the scope in which the destructor reference occurs. + /// \param Base the base object of the destructor reference expression. + /// \param OpLoc the location of the operator ('.' or '->'). + /// \param OpKind the kind of the destructor reference operator ('.' or '->'). + /// \param TypeRange the source range that covers the destructor type. + /// \param Type the type that is being destroyed. + /// \param SS the scope specifier that precedes the destructor name. + /// \param HasTrailingLParen whether the destructor name is followed by a '('. + virtual OwningExprResult + ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceRange TypeRange, + TypeTy *Type, + const CXXScopeSpec &SS, + bool HasTrailingLParen) { + return ExprEmpty(); + } + /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator /// reference, for example: /// @@ -1691,9 +1719,25 @@ public: /// possibly checking well-formedness of the template arguments. It does not /// imply the declaration of any entity. /// + /// \param SS The scope specifier that may precede the template name. + /// /// \param Template A template whose specialization results in a /// function or a dependent template. - virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template, + /// + /// \param TemplateNameLoc The location of the template name. + /// + /// \param LAngleLoc The location of the left angle bracket ('<') that starts + /// the template argument list. + /// + /// \param TemplateArgs The template arguments in the template argument list, + /// which may be empty. + /// + /// \param TemplateArgLocs The locations of the template arguments. + /// + /// \param RAngleLoc The location of the right angle bracket ('>') that + /// closes the template argument list. + virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, |