diff options
Diffstat (limited to 'include')
68 files changed, 2224 insertions, 1081 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 44cbe0efff81..1a58f44ff4c2 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -16,10 +16,23 @@ #ifndef CLANG_C_INDEX_H #define CLANG_C_INDEX_H +#include <sys/stat.h> + #ifdef __cplusplus extern "C" { #endif +/* MSVC DLL import/export. */ +#ifdef _MSC_VER + #ifdef _CINDEX_LIB_ + #define CINDEX_LINKAGE __declspec(dllexport) + #else + #define CINDEX_LINKAGE __declspec(dllimport) + #endif +#else + #define CINDEX_LINKAGE +#endif + /* Clang indeX abstractions. The backing store for the following API's will be clangs AST file (currently based on PCH). AST files are created as follows: @@ -33,6 +46,7 @@ typedef void *CXIndex; /* An indexing instance. */ typedef void *CXTranslationUnit; /* A translation unit instance. */ +typedef void *CXFile; /* A source file */ typedef void *CXDecl; /* A specific declaration within a translation unit. */ typedef void *CXStmt; /* A specific statement within a function/method */ @@ -138,22 +152,22 @@ typedef void *CXEntity; * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks * (which gives the indexer the same performance benefit as the compiler). */ -CXIndex clang_createIndex(int excludeDeclarationsFromPCH, +CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics); -void clang_disposeIndex(CXIndex); +CINDEX_LINKAGE void clang_disposeIndex(CXIndex); -const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); +CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); /* * \brief Create a translation unit from an AST file (-emit-ast). */ -CXTranslationUnit clang_createTranslationUnit( +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit( CXIndex, const char *ast_filename ); /** * \brief Destroy the specified CXTranslationUnit object. */ -void clang_disposeTranslationUnit(CXTranslationUnit); +CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); /** * \brief Return the CXTranslationUnit for a given source file and the provided @@ -170,7 +184,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit); * '-o <output file>' (both '-o' and '<output file>' are ignored) * */ -CXTranslationUnit clang_createTranslationUnitFromSourceFile( +CINDEX_LINKAGE 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, @@ -197,7 +211,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile( typedef void *CXClientData; typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor, CXClientData); -void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator, +CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator, CXClientData); /* @@ -227,23 +241,30 @@ void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator, */ typedef void (*CXDeclIterator)(CXDecl, CXCursor, CXClientData); -void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData); +CINDEX_LINKAGE void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData); + +/* + * CXFile Operations. + */ +CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile); +CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile); /* * CXEntity Operations. */ -const char *clang_getDeclarationName(CXEntity); -const char *clang_getURI(CXEntity); -CXEntity clang_getEntity(const char *URI); +CINDEX_LINKAGE const char *clang_getDeclarationName(CXEntity); +CINDEX_LINKAGE const char *clang_getURI(CXEntity); +CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI); /* * CXDecl Operations. */ -CXCursor clang_getCursorFromDecl(CXDecl); -CXEntity clang_getEntityFromDecl(CXDecl); -const char *clang_getDeclSpelling(CXDecl); -unsigned clang_getDeclLine(CXDecl); -unsigned clang_getDeclColumn(CXDecl); -const char *clang_getDeclSource(CXDecl); +CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl); +CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl); +CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl); +CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl); +CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl); +CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */ +CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl); /* * CXCursor Operations. @@ -252,38 +273,24 @@ const char *clang_getDeclSource(CXDecl); 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, +CINDEX_LINKAGE 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); -unsigned clang_isDefinition(enum CXCursorKind); -unsigned clang_isInvalid(enum CXCursorKind); +CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor); +CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind); +CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind); +CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind); +CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); -unsigned clang_getCursorLine(CXCursor); -unsigned clang_getCursorColumn(CXCursor); -const char *clang_getCursorSource(CXCursor); -const char *clang_getCursorSpelling(CXCursor); +CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor); +CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor); +CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor); +CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */ +CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor); /* for debug/testing */ -const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); -void clang_getDefinitionSpellingAndExtent(CXCursor, +CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); +CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, const char **startBuf, const char **endBuf, unsigned *startLine, @@ -296,7 +303,7 @@ void clang_getDefinitionSpellingAndExtent(CXCursor, * declaration. * If CXCursorKind == Cursor_Declaration, then this will return the declaration. */ -CXDecl clang_getCursorDecl(CXCursor); +CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor); #ifdef __cplusplus } diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 30896c91a143..7392170be995 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -16,6 +16,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" @@ -301,22 +302,22 @@ public: const char *getCommentForDecl(const Decl *D); // Builtin Types. - QualType VoidTy; - QualType BoolTy; - QualType CharTy; - QualType WCharTy; // [C++ 3.9.1p5], integer type in C99. - QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. - QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. - QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; - QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; - QualType UnsignedLongLongTy, UnsignedInt128Ty; - QualType FloatTy, DoubleTy, LongDoubleTy; - QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; - QualType VoidPtrTy, NullPtrTy; - QualType OverloadTy; - QualType DependentTy; - QualType UndeducedAutoTy; - QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; + CanQualType VoidTy; + CanQualType BoolTy; + CanQualType CharTy; + CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. + CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. + CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; + CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; + CanQualType UnsignedLongLongTy, UnsignedInt128Ty; + CanQualType FloatTy, DoubleTy, LongDoubleTy; + CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + CanQualType VoidPtrTy, NullPtrTy; + CanQualType OverloadTy; + CanQualType DependentTy; + CanQualType UndeducedAutoTy; + CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, @@ -387,10 +388,16 @@ public: /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T); + CanQualType getComplexType(CanQualType T) { + return CanQualType::CreateUnsafe(getComplexType((QualType) T)); + } /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. QualType getPointerType(QualType T); + CanQualType getPointerType(CanQualType T) { + return CanQualType::CreateUnsafe(getPointerType((QualType) T)); + } /// getBlockPointerType - Return the uniqued reference to the type for a block /// of the specified type. @@ -525,6 +532,11 @@ public: unsigned NumArgs, QualType Canon = QualType()); + QualType getTemplateSpecializationType(TemplateName T, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + QualType Canon = QualType()); + QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); QualType getTypenameType(NestedNameSpecifier *NNS, @@ -728,6 +740,8 @@ public: TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, const IdentifierInfo *Name); + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + OverloadedOperatorKind Operator); enum GetBuiltinTypeError { GE_None, //< No error @@ -739,7 +753,7 @@ public: QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error); private: - QualType getFromTargetType(unsigned Type) const; + CanQualType getFromTargetType(unsigned Type) const; //===--------------------------------------------------------------------===// // Type Predicates. @@ -826,6 +840,8 @@ public: llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI); unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD); + void CollectInheritedProtocols(const Decl *CDecl, + llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols); //===--------------------------------------------------------------------===// // Type Operators @@ -1013,7 +1029,9 @@ public: bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, const ObjCInterfaceType *RHS); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); - + QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + // Functions for calculating composite types QualType mergeTypes(QualType, QualType); QualType mergeFunctionTypes(QualType, QualType); @@ -1085,12 +1103,18 @@ public: /// should be calculated based on the type. DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0); + /// \brief Allocate a DeclaratorInfo where all locations have been + /// initialized to a given location, which defaults to the empty + /// location. + DeclaratorInfo * + getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation()); + private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT void operator=(const ASTContext&); // DO NOT IMPLEMENT void InitBuiltinTypes(); - void InitBuiltinType(QualType &R, BuiltinType::Kind K); + void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); // Return the ObjC type encoding for a given type. void getObjCEncodingForTypeImpl(QualType t, std::string &S, @@ -1103,6 +1127,18 @@ private: const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); }; + +/// @brief Utility function for constructing a nullary selector. +static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(0, &II); +} + +/// @brief Utility function for constructing an unary selector. +static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(1, &II); +} } // end namespace clang diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 8b84bc267997..a7750517090e 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -64,15 +64,6 @@ public: CanQual(const CanQual<U>& Other, typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0); - /// \brief Implicit conversion to the underlying pointer. - /// - /// Also provides the ability to use canonical types in a boolean context, - /// e.g., - /// @code - /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } - /// @endcode - operator const T*() const { return getTypePtr(); } - /// \brief Retrieve the underlying type pointer, which refers to a /// canonical type. T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); } @@ -80,6 +71,10 @@ public: /// \brief Implicit conversion to a qualified type. operator QualType() const { return Stored; } + bool isNull() const { + return Stored.isNull(); + } + /// \brief Retrieve a canonical type pointer with a different static type, /// upcasting or downcasting as needed. /// @@ -125,8 +120,10 @@ public: /// \brief Retrieve the unqualified form of this type. CanQual<T> getUnqualifiedType() const; - CanQual<T> getQualifiedType(unsigned TQs) const { - return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs)); + /// \brief Retrieves a version of this type with const applied. + /// Note that this does not always yield a canonical type. + QualType withConst() const { + return Stored.withConst(); } /// \brief Determines whether this canonical type is more qualified than diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 72ce0d852cfc..813e83accdb1 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -605,6 +605,9 @@ public: /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. bool isOutOfLine() const; + + /// \brief If this is a static data member, find its out-of-line definition. + VarDecl *getOutOfLineDefinition(); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -768,7 +771,11 @@ public: Init = (UnparsedDefaultArgument *)0; } - QualType getOriginalType() const; + QualType getOriginalType() const { + if (getDeclaratorInfo()) + return getDeclaratorInfo()->getType(); + return getType(); + } /// setOwningFunction - Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the @@ -778,41 +785,11 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { - return (D->getKind() == ParmVar || - D->getKind() == OriginalParmVar); + return (D->getKind() == ParmVar); } static bool classof(const ParmVarDecl *D) { return true; } }; -/// OriginalParmVarDecl - Represent a parameter to a function, when -/// the type of the parameter has been promoted. This node represents the -/// parameter to the function with its original type. -/// -class OriginalParmVarDecl : public ParmVarDecl { - friend class ParmVarDecl; -protected: - QualType OriginalType; -private: - OriginalParmVarDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo, - QualType OT, StorageClass S, - Expr *DefArg) - : ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg), - OriginalType(OT) {} -public: - static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, - QualType OT, StorageClass S, Expr *DefArg); - - void setOriginalType(QualType T) { OriginalType = T; } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; } - static bool classof(const OriginalParmVarDecl *D) { return true; } -}; - /// FunctionDecl - An instance of this class is created to represent a /// function declaration or definition. /// @@ -1067,9 +1044,18 @@ public: StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } - bool isInline() const { return IsInline; } - void setInline(bool I) { IsInline = I; } + /// \brief Determine whether the "inline" keyword was specified for this + /// function. + bool isInlineSpecified() const { return IsInline; } + + /// Set whether the "inline" keyword was specified for this function. + void setInlineSpecified(bool I) { IsInline = I; } + /// \brief Determine whether this function should be inlined, because it is + /// either marked "inline" or is a member function of a C++ class that + /// was defined in the class body. + bool isInlined() const; + bool isInlineDefinitionExternallyVisible() const; /// isOverloadedOperator - Whether this function declaration @@ -1146,7 +1132,17 @@ public: return TemplateOrSpecialization. dyn_cast<FunctionTemplateSpecializationInfo*>(); } - + + /// \brief Determines whether this function is a function template + /// specialization or a member of a class template specialization that can + /// be implicitly instantiated. + bool isImplicitlyInstantiable() const; + + /// \brief Retrieve the function declaration from which this function could + /// be instantiated, if it is an instantiation (rather than a non-template + /// or a specialization, for example). + FunctionDecl *getTemplateInstantiationPattern() const; + /// \brief Retrieve the primary template that this function template /// specialization either specializes or was instantiated from. /// @@ -1199,7 +1195,7 @@ public: /// 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. bool isOutOfLine() const; @@ -1337,20 +1333,29 @@ public: class TypedefDecl : public TypeDecl { /// UnderlyingType - This is the type the typedef is set to. - QualType UnderlyingType; + DeclaratorInfo *DInfo; + TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T) - : TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {} + IdentifierInfo *Id, DeclaratorInfo *DInfo) + : TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {} virtual ~TypedefDecl() {} public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, - QualType T); + SourceLocation L, IdentifierInfo *Id, + DeclaratorInfo *DInfo); + + DeclaratorInfo *getTypeDeclaratorInfo() const { + return DInfo; + } - QualType getUnderlyingType() const { return UnderlyingType; } - void setUnderlyingType(QualType newType) { UnderlyingType = newType; } + QualType getUnderlyingType() const { + return DInfo->getType(); + } + void setTypeDeclaratorInfo(DeclaratorInfo *newType) { + DInfo = newType; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Typedef; } diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index 790ea3ca0662..e1fae8f2ae67 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_DECLGROUP_H #define LLVM_CLANG_AST_DECLGROUP_H -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include <cassert> namespace clang { diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 79a0d368288c..3ef3cc3f0975 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -103,7 +103,6 @@ ABSTRACT_DECL(Named, Decl) DECL(Var, DeclaratorDecl) DECL(ImplicitParam, VarDecl) DECL(ParmVar, VarDecl) - DECL(OriginalParmVar, ParmVarDecl) DECL(NonTypeTemplateParm, VarDecl) DECL(Template, NamedDecl) DECL(FunctionTemplate, TemplateDecl) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 729a2f138303..bcd28eab039f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -347,6 +347,8 @@ public: ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; + ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass( + IdentifierInfo *PropertyId) const; // Marks the end of the container. SourceLocation getAtEndLoc() const { return AtEndLoc; } @@ -862,7 +864,7 @@ public: }; class ObjCImplDecl : public ObjCContainerDecl { - /// Class interface for this category implementation + /// Class interface for this class/category implementation ObjCInterfaceDecl *ClassInterface; protected: @@ -935,14 +937,20 @@ public: SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl *classInterface); - /// getIdentifier - Get the identifier that names the class + /// getIdentifier - Get the identifier that names the category /// interface associated with this implementation. + /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier() + /// to mean something different. For example: + /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() + /// returns the class interface name, whereas + /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() + /// returns the category name. IdentifierInfo *getIdentifier() const { return Id; } void setIdentifier(IdentifierInfo *II) { Id = II; } - ObjCCategoryDecl *getCategoryClass() const; + ObjCCategoryDecl *getCategoryDecl() const; /// getName - Get the name of identifier for the class interface associated /// with this implementation as a StringRef. diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 8d44676124fb..f1a27933a1b3 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -15,8 +15,7 @@ #define LLVM_CLANG_AST_DECLTEMPLATE_H #include "clang/AST/DeclCXX.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/FoldingSet.h" +#include "clang/AST/TemplateBase.h" #include "llvm/ADT/PointerUnion.h" #include <limits> @@ -91,6 +90,13 @@ public: /// arguments or if there is a parameter pack. unsigned getMinRequiredArguments() const; + /// \brief Get the depth of this template parameter list in the set of + /// template parameter lists. + /// + /// The first template parameter list in a declaration will have depth 0, + /// the second template parameter list will have depth 1, etc. + unsigned getDepth() const; + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -100,251 +106,6 @@ public: } }; -/// \brief Represents a template argument within a class template -/// specialization. -class TemplateArgument { - union { - uintptr_t TypeOrValue; - struct { - char Value[sizeof(llvm::APSInt)]; - void *Type; - } Integer; - struct { - TemplateArgument *Args; - unsigned NumArgs; - bool CopyArgs; - } Args; - }; - - /// \brief Location of the beginning of this template argument. - SourceLocation StartLoc; - -public: - /// \brief The type of template argument we're storing. - enum ArgKind { - Null = 0, - /// The template argument is a type. Its value is stored in the - /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, - /// The template argument is a value- or type-dependent expression - /// stored in an Expr*. - Expression = 4, - - /// The template argument is actually a parameter pack. Arguments are stored - /// in the Args struct. - Pack = 5 - } Kind; - - /// \brief Construct an empty, invalid template argument. - TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } - - /// \brief Construct a template type argument. - TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { - TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); - StartLoc = Loc; - } - - /// \brief Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. - TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { - // FIXME: Need to be sure we have the "canonical" declaration! - TypeOrValue = reinterpret_cast<uintptr_t>(D); - StartLoc = Loc; - } - - /// \brief Construct an integral constant template argument. - TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, - QualType Type) - : Kind(Integral) { - new (Integer.Value) llvm::APSInt(Value); - Integer.Type = Type.getAsOpaquePtr(); - StartLoc = Loc; - } - - /// \brief Construct a template argument that is an expression. - /// - /// This form of template argument only occurs in template argument - /// lists used for dependent types and for expression; it will not - /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E); - - /// \brief Copy constructor for a template argument. - TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { - if (Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = new TemplateArgument[Args.NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = Other.Args.Args[I]; - } - else - TypeOrValue = Other.TypeOrValue; - StartLoc = Other.StartLoc; - } - - TemplateArgument& operator=(const TemplateArgument& Other) { - // FIXME: Does not provide the strong guarantee for exception - // safety. - using llvm::APSInt; - - // FIXME: Handle Packs - assert(Kind != Pack && "FIXME: Handle packs"); - assert(Other.Kind != Pack && "FIXME: Handle packs"); - - if (Kind == Other.Kind && Kind == Integral) { - // Copy integral values. - *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; - } else { - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); - - Kind = Other.Kind; - - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else - TypeOrValue = Other.TypeOrValue; - } - StartLoc = Other.StartLoc; - - return *this; - } - - ~TemplateArgument() { - using llvm::APSInt; - - if (Kind == Integral) - getAsIntegral()->~APSInt(); - else if (Kind == Pack && Args.CopyArgs) - delete[] Args.Args; - } - - /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return Kind; } - - /// \brief Determine whether this template argument has no value. - bool isNull() const { return Kind == Null; } - - /// \brief Retrieve the template argument as a type. - QualType getAsType() const { - if (Kind != Type) - return QualType(); - - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); - } - - /// \brief Retrieve the template argument as a declaration. - Decl *getAsDecl() const { - if (Kind != Declaration) - return 0; - return reinterpret_cast<Decl *>(TypeOrValue); - } - - /// \brief Retrieve the template argument as an integral value. - llvm::APSInt *getAsIntegral() { - if (Kind != Integral) - return 0; - return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); - } - - const llvm::APSInt *getAsIntegral() const { - return const_cast<TemplateArgument*>(this)->getAsIntegral(); - } - - /// \brief Retrieve the type of the integral value. - QualType getIntegralType() const { - if (Kind != Integral) - return QualType(); - - return QualType::getFromOpaquePtr(Integer.Type); - } - - void setIntegralType(QualType T) { - assert(Kind == Integral && - "Cannot set the integral type of a non-integral template argument"); - Integer.Type = T.getAsOpaquePtr(); - }; - - /// \brief Retrieve the template argument as an expression. - Expr *getAsExpr() const { - if (Kind != Expression) - return 0; - - return reinterpret_cast<Expr *>(TypeOrValue); - } - - /// \brief Iterator that traverses the elements of a template argument pack. - typedef const TemplateArgument * pack_iterator; - - /// \brief Iterator referencing the first argument of a template argument - /// pack. - pack_iterator pack_begin() const { - assert(Kind == Pack); - return Args.Args; - } - - /// \brief Iterator referencing one past the last argument of a template - /// argument pack. - pack_iterator pack_end() const { - assert(Kind == Pack); - return Args.Args + Args.NumArgs; - } - - /// \brief The number of template arguments in the given template argument - /// pack. - unsigned pack_size() const { - assert(Kind == Pack); - return Args.NumArgs; - } - - /// \brief Retrieve the location where the template argument starts. - SourceLocation getLocation() const { return StartLoc; } - - /// \brief Construct a template argument pack. - void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); - - /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const { - ID.AddInteger(Kind); - switch (Kind) { - case Null: - break; - - case Type: - getAsType().Profile(ID); - break; - - case Declaration: - ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); - break; - - case Integral: - getAsIntegral()->Profile(ID); - getIntegralType().Profile(ID); - break; - - case Expression: - getAsExpr()->Profile(ID, Context, true); - break; - - case Pack: - ID.AddInteger(Args.NumArgs); - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I].Profile(ID, Context); - } - } -}; - /// \brief A helper class for making template argument lists. class TemplateArgumentListBuilder { TemplateArgument *StructuredArgs; @@ -811,11 +572,8 @@ class TemplateTypeParmDecl : public TypeDecl { /// \brief Whether this is a parameter pack. bool ParameterPack : 1; - /// \brief The location of the default argument, if any. - SourceLocation DefaultArgumentLoc; - /// \brief The default template argument, if any. - QualType DefaultArgument; + DeclaratorInfo *DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, bool Typename, QualType Type, bool ParameterPack) @@ -837,13 +595,16 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return !DefaultArgument.isNull(); } + bool hasDefaultArgument() const { return DefaultArgument != 0; } /// \brief Retrieve the default argument, if any. - QualType getDefaultArgument() const { return DefaultArgument; } + QualType getDefaultArgument() const { return DefaultArgument->getType(); } - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; } + /// \brief Retrieves the default argument's source information, if any. + DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; } + + /// \brief Retrieves the location of the default argument declaration. + SourceLocation getDefaultArgumentLoc() const; /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. @@ -852,13 +613,23 @@ public: /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc, - bool Inherited) { + void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) { DefaultArgument = DefArg; - DefaultArgumentLoc = DefArgLoc; InheritedDefault = Inherited; } + /// \brief Removes the default argument of this template parameter. + void removeDefaultArgument() { + DefaultArgument = 0; + InheritedDefault = false; + } + + /// \brief Retrieve the depth of the template parameter. + unsigned getDepth() const; + + /// \brief Retrieve the index of the template parameter. + unsigned getIndex() const; + /// \brief Returns whether this is a parameter pack. bool isParameterPack() const { return ParameterPack; } @@ -1150,17 +921,32 @@ class ClassTemplatePartialSpecializationDecl /// \brief The list of template parameters TemplateParameterList* TemplateParams; + /// \brief The source info for the template arguments as written. + TemplateArgumentLoc *ArgsAsWritten; + unsigned NumArgsAsWritten; + + /// \brief The class template partial specialization from which this + /// class template partial specialization was instantiated. + /// + /// The boolean value will be true to indicate that this class template + /// partial specialization was specialized at this level. + llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> + InstantiatedFromMember; + ClassTemplatePartialSpecializationDecl(ASTContext &Context, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, + TemplateArgumentLoc *ArgInfos, + unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, DC, L, SpecializedTemplate, Builder, PrevDecl), - TemplateParams(Params) { } + TemplateParams(Params), ArgsAsWritten(ArgInfos), + NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -1168,6 +954,8 @@ public: TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, + TemplateArgumentLoc *ArgInfos, + unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl); /// Get the list of template parameters @@ -1175,6 +963,80 @@ public: return TemplateParams; } + /// Get the template arguments as written. + TemplateArgumentLoc *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + + /// Get the number of template arguments as written. + unsigned getNumTemplateArgsAsWritten() const { + return NumArgsAsWritten; + } + + /// \brief Retrieve the member class template partial specialization from + /// which this particular class template partial specialization was + /// instantiated. + /// + /// \code + /// template<typename T> + /// struct Outer { + /// template<typename U> struct Inner; + /// template<typename U> struct Inner<U*> { }; // #1 + /// }; + /// + /// Outer<float>::Inner<int*> ii; + /// \endcode + /// + /// In this example, the instantiation of \c Outer<float>::Inner<int*> will + /// end up instantiating the partial specialization + /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class + /// template partial specialization \c Outer<T>::Inner<U*>. Given + /// \c Outer<float>::Inner<U*>, this function would return + /// \c Outer<T>::Inner<U*>. + ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + return First->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *PartialSpec) { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + First->InstantiatedFromMember.setPointer(PartialSpec); + } + + /// \brief Determines whether this class template partial specialization + /// template was a specialization of a member partial specialization. + /// + /// In the following example, the member template partial specialization + /// \c X<int>::Inner<T*> is a member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> struct Inner; + /// template<typename U> struct Inner<U*>; + /// }; + /// + /// template<> template<typename T> + /// struct X<int>::Inner<T*> { /* ... */ }; + /// \endcode + bool isMemberSpecialization() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + return First->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + assert(First->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + return First->InstantiatedFromMember.setInt(true); + } + // FIXME: Add Profile support! static bool classof(const Decl *D) { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0d09ea325c31..2a87f5883588 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -34,6 +34,7 @@ namespace clang { class BlockDecl; class CXXOperatorCallExpr; class CXXMemberCallExpr; + class TemplateArgumentLoc; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -134,7 +135,7 @@ public: /// with location to warn on and the source range[s] to report with the /// warning. bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, - SourceRange &R2) const; + SourceRange &R2, ASTContext &Ctx) const; /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or /// incomplete type other than void. Nonarray expressions that can be lvalues: @@ -241,6 +242,10 @@ public: /// in Result. bool Evaluate(EvalResult &Result, ASTContext &Ctx) const; + /// EvaluateAsAny - The same as Evaluate, except that it also succeeds on + /// stack based objects. + bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const; + /// isEvaluatable - Call Evaluate to see if this expression can be constant /// folded, but discard the result. bool isEvaluatable(ASTContext &Ctx) const; @@ -322,47 +327,221 @@ public: // Primary Expressions. //===----------------------------------------------------------------------===// +/// \brief Represents the qualifier that may precede a C++ name, e.g., the +/// "std::" in "std::sort". +struct NameQualifier { + /// \brief The nested name specifier. + NestedNameSpecifier *NNS; + + /// \brief The source range covered by the nested name specifier. + SourceRange Range; +}; + +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "<int>" in "sort<int>". +struct ExplicitTemplateArgumentList { + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// \brief Retrieve the template arguments + TemplateArgumentLoc *getTemplateArgs() { + return reinterpret_cast<TemplateArgumentLoc *> (this + 1); + } + + /// \brief Retrieve the template arguments + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); + } +}; + /// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, /// enum, etc. class DeclRefExpr : public Expr { - NamedDecl *D; + enum { + // Flag on DecoratedD that specifies when this declaration reference + // expression has a C++ nested-name-specifier. + HasQualifierFlag = 0x01, + // Flag on DecoratedD that specifies when this declaration reference + // expression has an explicit C++ template argument list. + HasExplicitTemplateArgumentListFlag = 0x02 + }; + + // DecoratedD - The declaration that we are referencing, plus two bits to + // indicate whether (1) the declaration's name was explicitly qualified and + // (2) the declaration's name was followed by an explicit template + // argument list. + llvm::PointerIntPair<NamedDecl *, 2> DecoratedD; + + // Loc - The location of the declaration name itself. SourceLocation Loc; + /// \brief Retrieve the qualifier that preceded the declaration name, if any. + NameQualifier *getNameQualifier() { + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return 0; + + return reinterpret_cast<NameQualifier *> (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const NameQualifier *getNameQualifier() const { + return const_cast<DeclRefExpr *>(this)->getNameQualifier(); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0) + return 0; + + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return reinterpret_cast<ExplicitTemplateArgumentList *>( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList(); + } + + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + NamedDecl *D, SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD); + protected: // FIXME: Eventually, this constructor will go away and all subclasses // will have to provide the type- and value-dependent flags. DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : - Expr(SC, t), D(d), Loc(l) {} + Expr(SC, t), DecoratedD(d, 0), Loc(l) {} DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : - Expr(SC, t, TD, VD), D(d), Loc(l) {} + Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {} public: // FIXME: Eventually, this constructor will go away and all clients // will have to provide the type- and value-dependent flags. DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : - Expr(DeclRefExprClass, t), D(d), Loc(l) {} + Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {} DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : - Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {} + Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {} /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - NamedDecl *getDecl() { return D; } - const NamedDecl *getDecl() const { return D; } - void setDecl(NamedDecl *NewD) { D = NewD; } + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + QualType T, bool TD, bool VD); + + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD); + + NamedDecl *getDecl() { return DecoratedD.getPointer(); } + const NamedDecl *getDecl() const { return DecoratedD.getPointer(); } + void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + virtual SourceRange getSourceRange() const; + /// \brief Determine whether this declaration reference was preceded by a + /// C++ nested-name-specifier, e.g., \c N::foo. + bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } + + /// \brief If the name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!hasQualifier()) + return SourceRange(); + + return getNameQualifier()->Range; + } + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name. Otherwise, returns NULL. + NestedNameSpecifier *getQualifier() const { + if (!hasQualifier()) + return 0; + + return getNameQualifier()->NNS; + } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() const { + return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass || - T->getStmtClass() == CXXConditionDeclExprClass || - T->getStmtClass() == QualifiedDeclRefExprClass; + T->getStmtClass() == CXXConditionDeclExprClass; } static bool classof(const DeclRefExpr *) { return true; } @@ -797,7 +976,7 @@ class SizeOfAlignOfExpr : public Expr { bool isSizeof : 1; // true if sizeof, false if alignof. bool isType : 1; // true if operand is a type, false if an expression union { - void *Ty; + DeclaratorInfo *Ty; Stmt *Ex; } Argument; SourceLocation OpLoc, RParenLoc; @@ -806,15 +985,15 @@ protected: virtual void DoDestroy(ASTContext& C); public: - SizeOfAlignOfExpr(bool issizeof, QualType T, + SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo, QualType resultType, SourceLocation op, SourceLocation rp) : Expr(SizeOfAlignOfExprClass, resultType, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. - T->isDependentType()), + DInfo->getType()->isDependentType()), isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { - Argument.Ty = T.getAsOpaquePtr(); + Argument.Ty = DInfo; } SizeOfAlignOfExpr(bool issizeof, Expr *E, @@ -837,8 +1016,11 @@ public: bool isArgumentType() const { return isType; } QualType getArgumentType() const { + return getArgumentTypeInfo()->getType(); + } + DeclaratorInfo *getArgumentTypeInfo() const { assert(isArgumentType() && "calling getArgumentType() when arg is expr"); - return QualType::getFromOpaquePtr(Argument.Ty); + return Argument.Ty; } Expr *getArgumentExpr() { assert(!isArgumentType() && "calling getArgumentExpr() when arg is type"); @@ -849,8 +1031,8 @@ public: } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } - void setArgument(QualType T) { - Argument.Ty = T.getAsOpaquePtr(); + void setArgument(DeclaratorInfo *DInfo) { + Argument.Ty = DInfo; isType = true; } @@ -1062,41 +1244,6 @@ public: virtual child_iterator child_end(); }; -/// \brief Represents the qualifier that may precede a C++ name, e.g., the -/// "std::" in "std::sort". -struct NameQualifier { - /// \brief The nested name specifier. - NestedNameSpecifier *NNS; - - /// \brief The source range covered by the nested name specifier. - SourceRange Range; -}; - -/// \brief Represents an explicit template argument list in C++, e.g., -/// the "<int>" in "sort<int>". -struct ExplicitTemplateArgumentList { - /// \brief The source location of the left angle bracket ('<'); - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'); - SourceLocation RAngleLoc; - - /// \brief The number of template arguments in TemplateArgs. - /// The actual template arguments (if any) are stored after the - /// ExplicitTemplateArgumentList structure. - unsigned NumTemplateArgs; - - /// \brief Retrieve the template arguments - TemplateArgument *getTemplateArgs() { - return reinterpret_cast<TemplateArgument *> (this + 1); - } - - /// \brief Retrieve the template arguments - const TemplateArgument *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgument *> (this + 1); - } -}; - /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr : public Expr { @@ -1161,7 +1308,7 @@ class MemberExpr : public Expr { MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, bool has_explicit, SourceLocation langle, - const TemplateArgument *targs, unsigned numtargs, + const TemplateArgumentLoc *targs, unsigned numtargs, SourceLocation rangle, QualType ty); public: @@ -1183,7 +1330,7 @@ public: SourceLocation l, bool has_explicit, SourceLocation langle, - const TemplateArgument *targs, + const TemplateArgumentLoc *targs, unsigned numtargs, SourceLocation rangle, QualType ty); @@ -1240,7 +1387,7 @@ public: /// \brief Retrieve the template arguments provided as part of this /// template-id. - const TemplateArgument *getTemplateArgs() const { + const TemplateArgumentLoc *getTemplateArgs() const { if (!HasExplicitTemplateArgumentList) return 0; @@ -1388,6 +1535,10 @@ public: /// member pointer in derived class. CK_BaseToDerivedMemberPointer, + /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to + /// member pointer in base class. + CK_DerivedToBaseMemberPointer, + /// CK_UserDefinedConversion - Conversion using a user defined type /// conversion function. CK_UserDefinedConversion, @@ -1687,7 +1838,9 @@ public: bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } 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 isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; } + bool isBitwiseOp() const { return isBitwiseOp(Opc); } static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } bool isRelationalOp() const { return isRelationalOp(Opc); } @@ -1695,6 +1848,9 @@ public: static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } bool isEqualityOp() const { return isEqualityOp(Opc); } + static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; } + bool isComparisonOp() const { return isComparisonOp(Opc); } + static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; } bool isLogicalOp() const { return isLogicalOp(Opc); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 3f66b1f40bfc..5931a3fcf984 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1061,46 +1061,11 @@ public: virtual child_iterator child_end(); }; -/// QualifiedDeclRefExpr - A reference to a declared variable, -/// function, enum, etc., that includes a qualification, e.g., -/// "N::foo". -class QualifiedDeclRefExpr : public DeclRefExpr { - /// QualifierRange - The source range that covers the - /// nested-name-specifier. - SourceRange QualifierRange; - - /// \brief The nested-name-specifier that qualifies this declaration - /// name. - NestedNameSpecifier *NNS; - -public: - QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, - bool VD, SourceRange R, NestedNameSpecifier *NNS) - : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), - QualifierRange(R), NNS(NNS) { } - - /// \brief Retrieve the source range of the nested-name-specifier. - SourceRange getQualifierRange() const { return QualifierRange; } - - /// \brief Retrieve the nested-name-specifier that qualifies this - /// declaration. - NestedNameSpecifier *getQualifier() const { return NNS; } - - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == QualifiedDeclRefExprClass; - } - static bool classof(const QualifiedDeclRefExpr *) { return true; } -}; - /// \brief A qualified reference to a name whose declaration cannot /// yet be resolved. /// -/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that -/// it expresses a qualified reference to a declaration such as +/// UnresolvedDeclRefExpr is similar to eclRefExpr in that +/// it expresses a reference to a declaration such as /// X<T>::value. The difference, however, is that an /// UnresolvedDeclRefExpr node is used only within C++ templates when /// the qualification (e.g., X<T>::) refers to a dependent type. In @@ -1108,8 +1073,8 @@ public: /// declaration will differ from on instantiation of X<T> to the /// next. Therefore, UnresolvedDeclRefExpr keeps track of the /// qualifier (X<T>::) and the name of the entity being referenced -/// ("value"). Such expressions will instantiate to -/// QualifiedDeclRefExprs. +/// ("value"). Such expressions will instantiate to a DeclRefExpr once the +/// declaration can be found. class UnresolvedDeclRefExpr : public Expr { /// The name of the entity we will be referencing. DeclarationName Name; @@ -1126,6 +1091,7 @@ class UnresolvedDeclRefExpr : public Expr { NestedNameSpecifier *NNS; /// \brief Whether this expr is an address of (&) operand. + /// FIXME: Stash this bit into NNS! bool IsAddressOfOperand; public: @@ -1195,7 +1161,7 @@ class TemplateIdRefExpr : public Expr { NestedNameSpecifier *Qualifier, SourceRange QualifierRange, TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); @@ -1206,7 +1172,7 @@ public: Create(ASTContext &Context, QualType T, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs, + SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); /// \brief Retrieve the nested name specifier used to qualify the name of @@ -1232,8 +1198,8 @@ public: /// \brief Retrieve the template arguments provided as part of this /// template-id. - const TemplateArgument *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgument *>(this + 1); + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc *>(this + 1); } /// \brief Retrieve the number of template arguments provided as part of this @@ -1477,7 +1443,7 @@ class CXXUnresolvedMemberExpr : public Expr { SourceLocation MemberLoc, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); @@ -1508,7 +1474,7 @@ public: SourceLocation MemberLoc, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); @@ -1576,7 +1542,7 @@ public: /// \brief Retrieve the template arguments provided as part of this /// template-id. - const TemplateArgument *getTemplateArgs() const { + const TemplateArgumentLoc *getTemplateArgs() const { if (!HasExplicitTemplateArgumentList) return 0; diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 7490b1d66b3e..5f318ba0b33b 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_LAYOUTINFO_H #define LLVM_CLANG_AST_LAYOUTINFO_H -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" namespace clang { class ASTContext; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 458af1f14423..1e6871ff3b9c 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -88,6 +88,11 @@ public: return D; } + /// \brief Returns the most recent (re)declaration of this declaration. + const decl_type *getMostRecentDeclaration() const { + return getFirstDeclaration()->RedeclLink.getNext(); + } + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. void setPreviousDeclaration(decl_type *PrevDecl) { diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 2d523fffce74..f1aa2cd50f0f 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_AST_STMT_ITR_H #define LLVM_CLANG_AST_STMT_ITR_H -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include <cassert> #include <iterator> diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 8d7e4b5fc0a3..034029a16971 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -127,7 +127,6 @@ EXPR(CXXDeleteExpr , Expr) EXPR(CXXPseudoDestructorExpr, Expr) EXPR(UnresolvedFunctionNameExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) -EXPR(QualifiedDeclRefExpr , DeclRefExpr) EXPR(UnresolvedDeclRefExpr , Expr) EXPR(TemplateIdRefExpr , Expr) EXPR(CXXConstructExpr , Expr) diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h new file mode 100644 index 000000000000..bb14c62d7770 --- /dev/null +++ b/include/clang/AST/TemplateBase.h @@ -0,0 +1,366 @@ +//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides definitions which are common for all kinds of +// template representation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H +#define LLVM_CLANG_AST_TEMPLATEBASE_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/Support/ErrorHandling.h" +#include "clang/AST/Type.h" + +namespace llvm { + class FoldingSetNodeID; +} + +namespace clang { + +class Decl; +class Expr; +class DeclaratorInfo; + +/// \brief Represents a template argument within a class template +/// specialization. +class TemplateArgument { + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + struct { + TemplateArgument *Args; + unsigned NumArgs; + bool CopyArgs; + } Args; + }; + +public: + /// \brief The type of template argument we're storing. + enum ArgKind { + Null = 0, + /// The template argument is a type. Its value is stored in the + /// TypeOrValue field. + Type = 1, + /// The template argument is a declaration + Declaration = 2, + /// The template argument is an integral value stored in an llvm::APSInt. + Integral = 3, + /// The template argument is a value- or type-dependent expression + /// stored in an Expr*. + Expression = 4, + + /// The template argument is actually a parameter pack. Arguments are stored + /// in the Args struct. + Pack = 5 + } Kind; + + /// \brief Construct an empty, invalid template argument. + TemplateArgument() : TypeOrValue(0), Kind(Null) { } + + /// \brief Construct a template type argument. + TemplateArgument(QualType T) : Kind(Type) { + TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + } + + /// \brief Construct a template argument that refers to a + /// declaration, which is either an external declaration or a + /// template declaration. + TemplateArgument(Decl *D) : Kind(Declaration) { + // FIXME: Need to be sure we have the "canonical" declaration! + TypeOrValue = reinterpret_cast<uintptr_t>(D); + } + + /// \brief Construct an integral constant template argument. + TemplateArgument(const llvm::APSInt &Value, QualType Type) + : Kind(Integral) { + new (Integer.Value) llvm::APSInt(Value); + Integer.Type = Type.getAsOpaquePtr(); + } + + /// \brief Construct a template argument that is an expression. + /// + /// This form of template argument only occurs in template argument + /// lists used for dependent types and for expression; it will not + /// occur in a non-dependent, canonical template argument list. + TemplateArgument(Expr *E) : Kind(Expression) { + TypeOrValue = reinterpret_cast<uintptr_t>(E); + } + + /// \brief Copy constructor for a template argument. + TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { + if (Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else if (Kind == Pack) { + Args.NumArgs = Other.Args.NumArgs; + Args.Args = new TemplateArgument[Args.NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = Other.Args.Args[I]; + } + else + TypeOrValue = Other.TypeOrValue; + } + + TemplateArgument& operator=(const TemplateArgument& Other) { + // FIXME: Does not provide the strong guarantee for exception + // safety. + using llvm::APSInt; + + // FIXME: Handle Packs + assert(Kind != Pack && "FIXME: Handle packs"); + assert(Other.Kind != Pack && "FIXME: Handle packs"); + + if (Kind == Other.Kind && Kind == Integral) { + // Copy integral values. + *this->getAsIntegral() = *Other.getAsIntegral(); + Integer.Type = Other.Integer.Type; + } else { + // Destroy the current integral value, if that's what we're holding. + if (Kind == Integral) + getAsIntegral()->~APSInt(); + + Kind = Other.Kind; + + if (Other.Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else + TypeOrValue = Other.TypeOrValue; + } + + return *this; + } + + ~TemplateArgument() { + using llvm::APSInt; + + if (Kind == Integral) + getAsIntegral()->~APSInt(); + else if (Kind == Pack && Args.CopyArgs) + delete[] Args.Args; + } + + /// \brief Return the kind of stored template argument. + ArgKind getKind() const { return Kind; } + + /// \brief Determine whether this template argument has no value. + bool isNull() const { return Kind == Null; } + + /// \brief Retrieve the template argument as a type. + QualType getAsType() const { + if (Kind != Type) + return QualType(); + + return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); + } + + /// \brief Retrieve the template argument as a declaration. + Decl *getAsDecl() const { + if (Kind != Declaration) + return 0; + return reinterpret_cast<Decl *>(TypeOrValue); + } + + /// \brief Retrieve the template argument as an integral value. + llvm::APSInt *getAsIntegral() { + if (Kind != Integral) + return 0; + return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); + } + + const llvm::APSInt *getAsIntegral() const { + return const_cast<TemplateArgument*>(this)->getAsIntegral(); + } + + /// \brief Retrieve the type of the integral value. + QualType getIntegralType() const { + if (Kind != Integral) + return QualType(); + + return QualType::getFromOpaquePtr(Integer.Type); + } + + void setIntegralType(QualType T) { + assert(Kind == Integral && + "Cannot set the integral type of a non-integral template argument"); + Integer.Type = T.getAsOpaquePtr(); + }; + + /// \brief Retrieve the template argument as an expression. + Expr *getAsExpr() const { + if (Kind != Expression) + return 0; + + return reinterpret_cast<Expr *>(TypeOrValue); + } + + /// \brief Iterator that traverses the elements of a template argument pack. + typedef const TemplateArgument * pack_iterator; + + /// \brief Iterator referencing the first argument of a template argument + /// pack. + pack_iterator pack_begin() const { + assert(Kind == Pack); + return Args.Args; + } + + /// \brief Iterator referencing one past the last argument of a template + /// argument pack. + pack_iterator pack_end() const { + assert(Kind == Pack); + return Args.Args + Args.NumArgs; + } + + /// \brief The number of template arguments in the given template argument + /// pack. + unsigned pack_size() const { + assert(Kind == Pack); + return Args.NumArgs; + } + + /// \brief Construct a template argument pack. + void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); + + /// \brief Used to insert TemplateArguments into FoldingSets. + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; +}; + +/// Location information for a TemplateArgument. +struct TemplateArgumentLocInfo { +private: + union { + Expr *Expression; + DeclaratorInfo *Declarator; + }; + +#ifndef NDEBUG + enum Kind { + K_None, + K_DeclaratorInfo, + K_Expression + } Kind; +#endif + +public: + TemplateArgumentLocInfo() + : Expression(0) +#ifndef NDEBUG + , Kind(K_None) +#endif + {} + + TemplateArgumentLocInfo(DeclaratorInfo *DInfo) + : Declarator(DInfo) +#ifndef NDEBUG + , Kind(K_DeclaratorInfo) +#endif + {} + + TemplateArgumentLocInfo(Expr *E) + : Expression(E) +#ifndef NDEBUG + , Kind(K_Expression) +#endif + {} + + DeclaratorInfo *getAsDeclaratorInfo() const { + assert(Kind == K_DeclaratorInfo); + return Declarator; + } + + Expr *getAsExpr() const { + assert(Kind == K_Expression); + return Expression; + } + +#ifndef NDEBUG + void validateForArgument(const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Type: + assert(Kind == K_DeclaratorInfo); + break; + case TemplateArgument::Expression: + case TemplateArgument::Declaration: + assert(Kind == K_Expression); + break; + case TemplateArgument::Integral: + case TemplateArgument::Pack: + assert(Kind == K_None); + break; + case TemplateArgument::Null: + llvm::llvm_unreachable("source info for null template argument?"); + } + } +#endif +}; + +/// Location wrapper for a TemplateArgument. TemplateArgument is to +/// TemplateArgumentLoc as Type is to TypeLoc. +class TemplateArgumentLoc { + TemplateArgument Argument; + TemplateArgumentLocInfo LocInfo; + +public: + TemplateArgumentLoc() {} + + TemplateArgumentLoc(const TemplateArgument &Argument, + TemplateArgumentLocInfo Opaque) + : Argument(Argument), LocInfo(Opaque) { + } + + TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo) + : Argument(Argument), LocInfo(DInfo) { + assert(Argument.getKind() == TemplateArgument::Type); + } + + TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) + : Argument(Argument), LocInfo(E) { + assert(Argument.getKind() == TemplateArgument::Expression); + } + + /// \brief - Fetches the start location of the argument. + SourceLocation getLocation() const { + return getSourceRange().getBegin(); + } + + /// \brief - Fetches the full source range of the argument. + SourceRange getSourceRange() const; + + const TemplateArgument &getArgument() const { + return Argument; + } + + TemplateArgumentLocInfo getLocInfo() const { + return LocInfo; + } + + DeclaratorInfo *getSourceDeclaratorInfo() const { + assert(Argument.getKind() == TemplateArgument::Type); + return LocInfo.getAsDeclaratorInfo(); + } + + Expr *getSourceExpression() const { + assert(Argument.getKind() == TemplateArgument::Expression); + return LocInfo.getAsExpr(); + } + + Expr *getSourceDeclExpression() const { + assert(Argument.getKind() == TemplateArgument::Declaration); + return LocInfo.getAsExpr(); + } +}; + +} + +#endif diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 66ff34cf1e31..8ef8fb51416c 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -16,6 +16,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" +#include "clang/Basic/OperatorKinds.h" namespace llvm { class raw_ostream; @@ -224,10 +225,24 @@ public: class DependentTemplateName : public llvm::FoldingSetNode { /// \brief The nested name specifier that qualifies the template /// name. - NestedNameSpecifier *Qualifier; + /// + /// The bit stored in this qualifier describes whether the \c Name field + /// is interpreted as an IdentifierInfo pointer (when clear) or as an + /// overloaded operator kind (when set). + llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier; /// \brief The dependent template name. - const IdentifierInfo *Name; + union { + /// \brief The identifier template name. + /// + /// Only valid when the bit on \c Qualifier is clear. + const IdentifierInfo *Identifier; + + /// \brief The overloaded operator name. + /// + /// Only valid when the bit on \c Qualifier is set. + OverloadedOperatorKind Operator; + }; /// \brief The canonical template name to which this dependent /// template name refers. @@ -240,30 +255,70 @@ class DependentTemplateName : public llvm::FoldingSetNode { friend class ASTContext; DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Name) - : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { } + const IdentifierInfo *Identifier) + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(this) { } DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Name, + const IdentifierInfo *Identifier, TemplateName Canon) - : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { } + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(Canon) { } + DependentTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator) + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(this) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator, + TemplateName Canon) + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(Canon) { } + public: /// \brief Return the nested name specifier that qualifies this name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } + NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - /// \brief Return the name to which this dependent template name - /// refers. - const IdentifierInfo *getName() const { return Name; } + /// \brief Determine whether this template name refers to an identifier. + bool isIdentifier() const { return !Qualifier.getInt(); } + /// \brief Returns the identifier to which this template name refers. + const IdentifierInfo *getIdentifier() const { + assert(isIdentifier() && "Template name isn't an identifier?"); + return Identifier; + } + + /// \brief Determine whether this template name refers to an overloaded + /// operator. + bool isOverloadedOperator() const { return Qualifier.getInt(); } + + /// \brief Return the overloaded operator to which this template name refers. + OverloadedOperatorKind getOperator() const { + assert(isOverloadedOperator() && + "Template name isn't an overloaded operator?"); + return Operator; + } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getQualifier(), getName()); + if (isIdentifier()) + Profile(ID, getQualifier(), getIdentifier()); + else + Profile(ID, getQualifier(), getOperator()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + const IdentifierInfo *Identifier) { + ID.AddPointer(NNS); + ID.AddBoolean(false); + ID.AddPointer(Identifier); } static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - const IdentifierInfo *Name) { + OverloadedOperatorKind Operator) { ID.AddPointer(NNS); - ID.AddPointer(Name); + ID.AddBoolean(true); + ID.AddInteger(Operator); } }; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index db02a68a984d..daa814739182 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -81,6 +81,7 @@ namespace clang { class SourceLocation; class StmtIteratorBase; class TemplateArgument; + class TemplateArgumentLoc; class QualifiedNameType; struct PrintingPolicy; @@ -2275,12 +2276,19 @@ public: static bool anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, + unsigned NumArgs); + /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. static std::string PrintTemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, const PrintingPolicy &Policy); + static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args, + unsigned NumArgs, + const PrintingPolicy &Policy); + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 1d7181b531f8..da7857822e9c 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TYPELOC_H #include "clang/AST/Type.h" +#include "clang/AST/TemplateBase.h" namespace clang { class ParmVarDecl; @@ -82,6 +83,19 @@ public: return Data; } + /// \brief Get the full source range. + SourceRange getFullSourceRange() const { + SourceLocation End = getSourceRange().getEnd(); + TypeLoc Cur = *this; + while (true) { + TypeLoc Next = Cur.getNextTypeLoc(); + if (Next.isNull()) break; + Cur = Next; + } + return SourceRange(Cur.getSourceRange().getBegin(), End); + } + + /// \brief Get the local source range. SourceRange getSourceRange() const { return getSourceRangeImpl(*this); } @@ -761,6 +775,10 @@ public: getLocalData()->RBracketLoc = Loc; } + SourceRange getBracketsRange() const { + return SourceRange(getLBracketLoc(), getRBracketLoc()); + } + Expr *getSizeExpr() const { return getLocalData()->Size; } @@ -810,6 +828,118 @@ class VariableArrayTypeLoc : VariableArrayType> { }; + +// Location information for a TemplateName. Rudimentary for now. +struct TemplateNameLocInfo { + SourceLocation NameLoc; +}; + +struct TemplateSpecializationLocInfo : TemplateNameLocInfo { + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; +}; + +class TemplateSpecializationTypeLoc : + public ConcreteTypeLoc<UnqualTypeLoc, + TemplateSpecializationTypeLoc, + TemplateSpecializationType, + TemplateSpecializationLocInfo> { +public: + SourceLocation getLAngleLoc() const { + return getLocalData()->LAngleLoc; + } + void setLAngleLoc(SourceLocation Loc) { + getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return getLocalData()->RAngleLoc; + } + void setRAngleLoc(SourceLocation Loc) { + getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumArgs() const { + return getTypePtr()->getNumArgs(); + } + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { +#ifndef NDEBUG + AI.validateForArgument(getTypePtr()->getArg(i)); +#endif + getArgInfos()[i] = AI; + } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { + return getArgInfos()[i]; + } + + TemplateArgumentLoc getArgLoc(unsigned i) const { + return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + } + + SourceLocation getTemplateNameLoc() const { + return getLocalData()->NameLoc; + } + void setTemplateNameLoc(SourceLocation Loc) { + getLocalData()->NameLoc = Loc; + } + + /// \brief - Copy the location information from the given info. + void copy(TemplateSpecializationTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + + // We're potentially copying Expr references here. We don't + // bother retaining them because DeclaratorInfos live forever, so + // as long as the Expr was retained when originally written into + // the TypeLoc, we're okay. + memcpy(Data, Loc.Data, size); + } + + SourceRange getSourceRange() const { + return SourceRange(getTemplateNameLoc(), getRAngleLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setLAngleLoc(Loc); + setRAngleLoc(Loc); + setTemplateNameLoc(Loc); + + for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { + TemplateArgumentLocInfo Info; +#ifndef NDEBUG + // If asserts are enabled, be sure to initialize the argument + // loc with the right kind of pointer. + switch (getTypePtr()->getArg(i).getKind()) { + case TemplateArgument::Expression: + case TemplateArgument::Declaration: + Info = TemplateArgumentLocInfo((Expr*) 0); + break; + + case TemplateArgument::Type: + Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); + break; + + case TemplateArgument::Integral: + case TemplateArgument::Pack: + case TemplateArgument::Null: + // K_None is fine. + break; + } +#endif + getArgInfos()[i] = Info; + } + } + + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(TemplateArgumentLocInfo); + } + +private: + TemplateArgumentLocInfo *getArgInfos() const { + return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); + } +}; + // None of these types have proper implementations yet. class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> { @@ -861,11 +991,6 @@ class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc, ElaboratedType> { }; -class TemplateSpecializationTypeLoc - : public TypeSpecTypeLoc<TemplateSpecializationTypeLoc, - TemplateSpecializationType> { -}; - class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc, QualifiedNameType> { }; diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index fabeea38d597..5edfe6fea8db 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -17,7 +17,6 @@ #include "clang/Index/ASTLocation.h" #include "clang/Index/Entity.h" #include "clang/Index/Program.h" -#include "clang/Frontend/ASTUnit.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" @@ -87,7 +86,7 @@ public: CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; } - void addTU(ASTUnit &AST); + void addTU(ASTContext &AST); idx::Program &getProgram() { return Prog; } diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 8e02ccf38209..66e850a91444 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -80,6 +80,8 @@ protected: : Kind(k), Ctx(ctx), Parent(parent) {} public: + virtual ~LocationContext() {} + ContextKind getKind() const { return Kind; } AnalysisContext *getAnalysisContext() const { return Ctx; } @@ -102,7 +104,7 @@ public: return Ctx->getSelfDecl(); } - void Profile(llvm::FoldingSetNodeID &ID) { + virtual void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Kind, Ctx, Parent); } @@ -119,10 +121,13 @@ public: StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(StackFrame, ctx, parent), CallSite(s) {} + + virtual ~StackFrameContext() {} + Stmt const *getCallSite() const { return CallSite; } - void Profile(llvm::FoldingSetNodeID &ID) { + virtual void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAnalysisContext(), getParent(), CallSite); } @@ -141,8 +146,10 @@ public: ScopeContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(Scope, ctx, parent), Enter(s) {} + + virtual ~ScopeContext() {} - void Profile(llvm::FoldingSetNodeID &ID) { + virtual void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAnalysisContext(), getParent(), Enter); } diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 1434fce811d1..914118cb430d 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -19,6 +19,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Analysis/PathSensitive/GRState.h" #include "clang/Analysis/PathSensitive/ExplodedGraph.h" +#include "clang/Analysis/PathSensitive/BugType.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -183,38 +184,6 @@ public: const_iterator end() const { return const_iterator(Reports.end()); } }; -class BugType { -private: - const std::string Name; - const std::string Category; - llvm::FoldingSet<BugReportEquivClass> EQClasses; - friend class BugReporter; - bool SuppressonSink; -public: - BugType(const char *name, const char* cat) - : Name(name), Category(cat), SuppressonSink(false) {} - virtual ~BugType(); - - // FIXME: Should these be made strings as well? - const std::string& getName() const { return Name; } - const std::string& getCategory() const { return Category; } - - /// isSuppressOnSink - Returns true if bug reports associated with this bug - /// type should be suppressed if the end node of the report is post-dominated - /// by a sink node. - bool isSuppressOnSink() const { return SuppressonSink; } - void setSuppressOnSink(bool x) { SuppressonSink = x; } - - virtual void FlushReports(BugReporter& BR); - - typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator; - iterator begin() { return EQClasses.begin(); } - iterator end() { return EQClasses.end(); } - - typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator; - const_iterator begin() const { return EQClasses.begin(); } - const_iterator end() const { return EQClasses.end(); } -}; //===----------------------------------------------------------------------===// // Specialized subclasses of BugReport. diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h new file mode 100644 index 000000000000..46b3edd3172e --- /dev/null +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -0,0 +1,86 @@ +//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines BugType, a class representing a bug type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE +#define LLVM_CLANG_ANALYSIS_BUGTYPE + +#include <llvm/ADT/FoldingSet.h> +#include <string> + +namespace clang { + +class BugReportEquivClass; +class BugReporter; +class BuiltinBugReport; +class BugReporterContext; +class GRExprEngine; + +class BugType { +private: + const std::string Name; + const std::string Category; + llvm::FoldingSet<BugReportEquivClass> EQClasses; + friend class BugReporter; + bool SuppressonSink; +public: + BugType(const char *name, const char* cat) + : Name(name), Category(cat), SuppressonSink(false) {} + virtual ~BugType(); + + // FIXME: Should these be made strings as well? + const std::string& getName() const { return Name; } + const std::string& getCategory() const { return Category; } + + /// isSuppressOnSink - Returns true if bug reports associated with this bug + /// type should be suppressed if the end node of the report is post-dominated + /// by a sink node. + bool isSuppressOnSink() const { return SuppressonSink; } + void setSuppressOnSink(bool x) { SuppressonSink = x; } + + virtual void FlushReports(BugReporter& BR); + + typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator; + iterator begin() { return EQClasses.begin(); } + iterator end() { return EQClasses.end(); } + + typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator; + const_iterator begin() const { return EQClasses.begin(); } + const_iterator end() const { return EQClasses.end(); } +}; + +class BuiltinBug : public BugType { + GRExprEngine &Eng; +protected: + const std::string desc; +public: + BuiltinBug(GRExprEngine *eng, const char* n, const char* d) + : BugType(n, "Logic errors"), Eng(*eng), desc(d) {} + + BuiltinBug(GRExprEngine *eng, const char* n) + : BugType(n, "Logic errors"), Eng(*eng), desc(n) {} + + const std::string &getDescription() const { return desc; } + + virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {} + + void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); } + + virtual void registerInitialVisitors(BugReporterContext& BRC, + const ExplodedNode* N, + BuiltinBugReport *R) {} + + template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E); +}; + +} // end clang namespace +#endif diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 4e00d69cdba1..3bef08d7545f 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -72,6 +72,10 @@ public: ASTContext &getASTContext() { return Eng.getContext(); } + + BugReporter &getBugReporter() { + return Eng.getBugReporter(); + } ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) { return GenerateNode(S, getState(), markAsSink); @@ -104,16 +108,42 @@ private: GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *stmt, - ExplodedNode *Pred, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, getTag(), isPrevisit); + ExplodedNode *Pred, void *tag, bool isPrevisit) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); assert(isPrevisit && "Only previsit supported for now."); _PreVisit(C, stmt); } + void GR_VisitBind(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, GRExprEngine &Eng, + const Stmt *stmt, ExplodedNode *Pred, void *tag, + SVal location, SVal val, + bool isPrevisit) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); + assert(isPrevisit && "Only previsit supported for now."); + PreVisitBind(C, stmt, location, val); + } + public: virtual ~Checker() {} - virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) = 0; - virtual const void *getTag() = 0; + virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {} + + // This is a previsit which takes a node returns a node. + virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, + const GRState *state, SVal V, + GRExprEngine &Eng) { + return Pred; + } + + virtual void PreVisitBind(CheckerContext &C, const Stmt *ST, + SVal location, SVal val) {} + + virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, + const GRState *state, Stmt *S, + GRExprEngine &Eng) { + return Pred; + } + }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h new file mode 100644 index 000000000000..007ec093b2e0 --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h @@ -0,0 +1,28 @@ +//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines AttrNonNullChecker, a builtin check in GRExprEngine that +// performs checks for arguments declared to have nonnull attribute. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/CheckerVisitor.h" + +namespace clang { + +class AttrNonNullChecker : public CheckerVisitor<AttrNonNullChecker> { + BugType *BT; + +public: + AttrNonNullChecker() : BT(0) {} + static void *getTag(); + void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); +}; + +} diff --git a/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h new file mode 100644 index 000000000000..70f3c44165e0 --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h @@ -0,0 +1,30 @@ +//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines BadCallChecker, a builtin check in GRExprEngine that performs +// checks for bad callee at call sites. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/CheckerVisitor.h" + +namespace clang { + +class BadCallChecker : public CheckerVisitor<BadCallChecker> { + BuiltinBug *BT; + +public: + BadCallChecker() : BT(0) {} + + static void *getTag(); + + void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); +}; + +} diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h new file mode 100644 index 000000000000..688cf641491d --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h @@ -0,0 +1,53 @@ +//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines NullDerefChecker and UndefDerefChecker, two builtin checks +// in GRExprEngine that check for null and undefined pointers at loads +// and stores. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DEREFCHECKER +#define LLVM_CLANG_DEREFCHECKER + +#include "clang/Analysis/PathSensitive/Checker.h" +#include "clang/Analysis/PathSensitive/BugType.h" + +namespace clang { + +class ExplodedNode; + +class NullDerefChecker : public Checker { + BuiltinBug *BT; + llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes; + +public: + NullDerefChecker() : BT(0) {} + ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, + const GRState *state, SVal V,GRExprEngine &Eng); + + static void *getTag(); + typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator; + iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); } + iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); } +}; + +class UndefDerefChecker : public Checker { + BuiltinBug *BT; +public: + UndefDerefChecker() : BT(0) {} + + ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, + const GRState *state, SVal V, GRExprEngine &Eng); + + static void *getTag(); +}; + +} // end clang namespace +#endif diff --git a/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h new file mode 100644 index 000000000000..317e43a0e62e --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h @@ -0,0 +1,28 @@ +//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines DivZeroChecker, a builtin check in GRExprEngine that performs +// checks for division by zeros. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/CheckerVisitor.h" + +namespace clang { + +class DivZeroChecker : public CheckerVisitor<DivZeroChecker> { + BuiltinBug *BT; +public: + DivZeroChecker() : BT(0) {} + + static void *getTag(); + void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); +}; + +} diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h new file mode 100644 index 000000000000..7f4e7d524f6c --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h @@ -0,0 +1,34 @@ +//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines BadCallChecker, a builtin check in GRExprEngine that performs +// checks for undefined arguments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_UNDEFARGCHECKER +#define LLVM_CLANG_UNDEFARGCHECKER + +#include "clang/Analysis/PathSensitive/CheckerVisitor.h" + +namespace clang { + +class UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> { + BugType *BT; + +public: + UndefinedArgChecker() : BT(0) {} + + static void *getTag(); + + void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); +}; + +} +#endif diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h new file mode 100644 index 000000000000..7fee5011c46d --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h @@ -0,0 +1,32 @@ +//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that +// checks for assigning undefined values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER +#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER + +#include "clang/Analysis/PathSensitive/CheckerVisitor.h" + +namespace clang { +class UndefinedAssignmentChecker + : public CheckerVisitor<UndefinedAssignmentChecker> { + BugType *BT; +public: + UndefinedAssignmentChecker() : BT(0) {} + static void *getTag(); + virtual void PreVisitBind(CheckerContext &C, const Stmt *S, SVal location, + SVal val); +}; +} +#endif + diff --git a/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h new file mode 100644 index 000000000000..b339b3d30141 --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h @@ -0,0 +1,39 @@ +//=== VLASizeChecker.h - Undefined dereference checker ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines two VLASizeCheckers, a builtin check in GRExprEngine that +// performs checks for declaration of VLA of undefined or zero size. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/Checker.h" + +namespace clang { + +class UndefSizedVLAChecker : public Checker { + BugType *BT; + +public: + UndefSizedVLAChecker() : BT(0) {} + static void *getTag(); + ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, + const GRState *state, Stmt *S, GRExprEngine &Eng); +}; + +class ZeroSizedVLAChecker : public Checker { + BugType *BT; + +public: + ZeroSizedVLAChecker() : BT(0) {} + static void *getTag(); + ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, + const GRState *state, Stmt *S, GRExprEngine &Eng); +}; + +} diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index e5c61e68c77c..2f2a11a83cea 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -75,7 +75,12 @@ class GRExprEngine : public GRSubEngine { Selector RaiseSel; llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor; - std::vector<Checker*> Checkers; + + typedef llvm::DenseMap<void *, unsigned> CheckerMap; + CheckerMap CheckerM; + + typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered; + CheckersOrdered Checkers; /// BR - The BugReporter associated with this engine. It is important that // this object be placed at the very end of member variables so that its @@ -126,18 +131,6 @@ public: // calling a function with the attribute "noreturn". ErrorNodes NoReturnCalls; - /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from - /// taking a dereference on a symbolic pointer that MAY be NULL. - ErrorNodes ImplicitNullDeref; - - /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from - /// taking a dereference on a symbolic pointer that MUST be NULL. - ErrorNodes ExplicitNullDeref; - - /// UndefDeref - Nodes in the ExplodedGraph that result from - /// taking a dereference on an undefined value. - ErrorNodes UndefDeref; - /// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from /// constructing a zero-sized VLA where the size may be zero. ErrorNodes ImplicitBadSizedVLA; @@ -158,10 +151,6 @@ public: /// ObjC message expressions where the receiver is undefined (uninitialized). ErrorNodes UndefReceivers; - /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions - /// where a pass-by-value argument has an undefined value. - UndefArgsTy UndefArgs; - /// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from /// message expressions where a pass-by-value argument has an undefined /// value. @@ -195,6 +184,8 @@ public: BugReporter& getBugReporter() { return BR; } + GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } + /// setTransferFunctions void setTransferFunctions(GRTransferFuncs* tf); @@ -217,8 +208,19 @@ public: void RegisterInternalChecks(); - void registerCheck(Checker *check) { - Checkers.push_back(check); + template <typename CHECKER> + void registerCheck(CHECKER *check) { + unsigned entry = Checkers.size(); + void *tag = CHECKER::getTag(); + Checkers.push_back(std::make_pair(tag, check)); + CheckerM[tag] = entry; + } + + Checker *lookupChecker(void *tag) const; + + template <typename CHECKER> + CHECKER *getChecker() const { + return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); } bool isRetStackAddr(const ExplodedNode* N) const { @@ -234,15 +236,15 @@ public: } bool isImplicitNullDeref(const ExplodedNode* N) const { - return N->isSink() && ImplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0; + return false; } bool isExplicitNullDeref(const ExplodedNode* N) const { - return N->isSink() && ExplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0; + return false; } bool isUndefDeref(const ExplodedNode* N) const { - return N->isSink() && UndefDeref.count(const_cast<ExplodedNode*>(N)) != 0; + return false; } bool isNoReturnCall(const ExplodedNode* N) const { @@ -254,13 +256,11 @@ public: } bool isBadCall(const ExplodedNode* N) const { - return N->isSink() && BadCalls.count(const_cast<ExplodedNode*>(N)) != 0; + return false; } bool isUndefArg(const ExplodedNode* N) const { - return N->isSink() && - (UndefArgs.find(const_cast<ExplodedNode*>(N)) != UndefArgs.end() || - MsgExprUndefArgs.find(const_cast<ExplodedNode*>(N)) != MsgExprUndefArgs.end()); + return false; } bool isUndefReceiver(const ExplodedNode* N) const { @@ -279,17 +279,6 @@ public: undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); } undef_branch_iterator undef_branches_end() { return UndefBranches.end(); } - typedef ErrorNodes::iterator null_deref_iterator; - null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); } - null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); } - - null_deref_iterator implicit_null_derefs_begin() { - return ImplicitNullDeref.begin(); - } - null_deref_iterator implicit_null_derefs_end() { - return ImplicitNullDeref.end(); - } - typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator; nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() { @@ -312,10 +301,6 @@ public: return NilReceiverLargerThanVoidPtrRetExplicit.end(); } - typedef ErrorNodes::iterator undef_deref_iterator; - undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); } - undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); } - typedef ErrorNodes::iterator undef_result_iterator; undef_result_iterator undef_results_begin() { return UndefResults.begin(); } undef_result_iterator undef_results_end() { return UndefResults.end(); } @@ -325,9 +310,6 @@ public: bad_calls_iterator bad_calls_end() { return BadCalls.end(); } typedef UndefArgsTy::iterator undef_arg_iterator; - undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); } - undef_arg_iterator undef_arg_end() { return UndefArgs.end(); } - undef_arg_iterator msg_expr_undef_arg_begin() { return MsgExprUndefArgs.begin(); } @@ -427,7 +409,12 @@ public: protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. - void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit); + void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + bool isPrevisit); + + void CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + SVal location, SVal val, bool isPrevisit); + /// Visit - Transfer function logic for all statements. Dispatches to /// other functions that handle specific kinds of statements. @@ -456,7 +443,8 @@ protected: ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitBinaryOperator - Transfer function logic for binary operators. - void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); /// VisitCall - Transfer function for function calls. @@ -578,8 +566,9 @@ protected: /// EvalBind - Handle the semantics of binding a value to a specific location. /// This method is used by EvalStore, VisitDeclStmt, and others. - void EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, - const GRState* St, SVal location, SVal Val); + void EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, SVal Val, + bool atDeclInit = false); public: void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index d8b9d560ccd8..8678ca9b5b9b 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -26,7 +26,7 @@ #include "clang/AST/ASTContext.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" @@ -219,11 +219,9 @@ public: const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; - const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC, - SVal V) const; + const GRState *bindDecl(const VarRegion *VR, SVal V) const; - const GRState *bindDeclWithNoInit(const VarDecl *VD, - const LocationContext *LC) const; + const GRState *bindDeclWithNoInit(const VarRegion *VR) const; const GRState *bindLoc(Loc location, SVal V) const; @@ -602,15 +600,12 @@ inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V); } -inline const GRState *GRState::bindDecl(const VarDecl* VD, - const LocationContext *LC, - SVal IVal) const { - return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal); +inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { + return getStateManager().StoreMgr->BindDecl(this, VR, IVal); } -inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD, - const LocationContext *LC) const { - return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC); +inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { + return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR); } inline const GRState *GRState::bindLoc(Loc LV, SVal V) const { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 5f7b2cb0e327..40c1ed3224f4 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -23,7 +23,6 @@ namespace clang { class GRExprEngine; -class BugReporter; class ObjCMessageExpr; class GRStmtNodeBuilderRef; @@ -33,7 +32,7 @@ public: virtual ~GRTransferFuncs() {} virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {} - virtual void RegisterChecks(BugReporter& BR) {} + virtual void RegisterChecks(GRExprEngine& Eng) {} // Calls. @@ -78,7 +77,7 @@ public: virtual const GRState* EvalAssume(const GRState *state, SVal Cond, bool Assumption) { return state; - } + } }; GRTransferFuncs *CreateCallInliner(ASTContext &ctx); diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 7a462c579f9f..6ca2e9e9aa68 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -134,12 +134,11 @@ public: SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; - virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD, - const LocationContext *LC, SVal initVal) = 0; + virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR, + SVal initVal) = 0; virtual const GRState *BindDeclWithNoInit(const GRState *ST, - const VarDecl *VD, - const LocationContext *LC) = 0; + const VarRegion *VR) = 0; typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h index d3996c6330a2..167a102e94ec 100644 --- a/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -18,7 +18,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/Analysis/Analyses/LiveVariables.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/DenseSet.h" diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 666e45b847cf..7aaae9c86653 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT #include "clang/Analysis/CFG.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Casting.h" diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index 3826d3a3acd6..afc63616e9fc 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -57,7 +57,6 @@ public: DISPATCH_CASE(Function,FunctionDecl) DISPATCH_CASE(Var,VarDecl) DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) - DISPATCH_CASE(OriginalParmVar,OriginalParmVarDecl) // FIXME: (same) DISPATCH_CASE(ImplicitParam,ImplicitParamDecl) DISPATCH_CASE(EnumConstant,EnumConstantDecl) DISPATCH_CASE(Typedef,TypedefDecl) @@ -70,7 +69,6 @@ public: DEFAULT_DISPATCH(VarDecl) DEFAULT_DISPATCH(FunctionDecl) - DEFAULT_DISPATCH_VARDECL(OriginalParmVarDecl) DEFAULT_DISPATCH_VARDECL(ParmVarDecl) DEFAULT_DISPATCH(ImplicitParamDecl) DEFAULT_DISPATCH(EnumConstantDecl) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 27997858c00c..98c703d94e92 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -329,7 +329,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:") BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:") BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") -BUILTIN(__builtin_expect, "iii" , "nc") +BUILTIN(__builtin_expect, "LiLiLi" , "nc") BUILTIN(__builtin_prefetch, "vvC*.", "nc") BUILTIN(__builtin_abort, "v", "Fnr") BUILTIN(__builtin_trap, "v", "nr") diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index cbf9cdbc1599..bb251ad73bd8 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -52,8 +52,4 @@ def warn_integer_too_large_for_signed : Warning< def note_invalid_subexpr_in_ice : Note< "subexpression not valid in an integer constant expression">; -// clang-cc -def err_pp_I_dash_not_supported : Error< - "-I- not supported, please use -iquote instead">; - } diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index dfdf0ff2e733..e2f11041dce2 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -55,6 +55,8 @@ def err_drv_command_signalled : Error< "%0 command failed due to signal %1 (use -v to see invocation)">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; +def err_drv_I_dash_not_supported : Error< + "'%0' not supported, please use -iquote instead">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index e5c73270fdfc..ae8b92394443 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -12,6 +12,7 @@ let Component = "Frontend" in { def err_fe_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">; +def err_fe_error_opening : Error<"error opening '%0': %1">; def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; @@ -19,6 +20,8 @@ def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; def err_fe_invalid_code_complete_file : Error<"cannot locate code-completion file %0">, DefaultFatal; +def err_fe_dependency_file_requires_MT : Error< + "-dependency-file requires at least one -MT option">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 3f132c0dabfa..bbc551373d96 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -194,7 +194,8 @@ def err_pp_expected_eol : Error< "expected end of line in preprocessor expression">; def err_pp_defined_requires_identifier : Error< "operator 'defined' requires an identifier">; -def err_pp_missing_rparen : Error<"missing ')' after 'defined'">; +def err_pp_missing_lparen : Error<"missing '(' after '%0'">; +def err_pp_missing_rparen : Error<"missing ')' after '%0'">; def err_pp_colon_without_question : Error<"':' without preceding '?'">; def err_pp_division_by_zero : Error< "division by zero in preprocessor expression">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 19b0ea3932a5..db8d580a2cd7 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -117,6 +117,8 @@ def err_expected_semi_after_static_assert : Error< "expected ';' after static_assert">; def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">; def err_expected_colon_after : Error<"expected ':' after %0">; +def err_pointer_to_member_type : Error< + "invalid use of pointer to member type after %0">; def err_label_end_of_compound_statement : Error< "label at end of compound statement: expected statement">; def err_expected_string_literal : Error<"expected string literal">; @@ -124,6 +126,7 @@ def err_expected_asm_operand : Error< "expected string literal or '[' for asm operand">; def err_expected_selector_for_method : Error< "expected selector for Objective-C method">; +def err_expected_property_name : Error<"expected property name">; def err_unexpected_at : Error<"unexpected '@' in program">; @@ -213,7 +216,8 @@ def err_declaration_does_not_declare_param : Error< def err_no_matching_param : Error<"parameter named %0 is missing">; /// C++ parser diagnostics -def err_expected_unqualified_id : Error<"expected unqualified-id">; +def err_expected_unqualified_id : Error< + "expected %select{identifier|unqualified-id}0">; def err_func_def_no_params : Error< "function definition does not declare parameters">; def err_expected_lparen_after_type : Error< @@ -230,6 +234,8 @@ def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; def err_using_namespace_in_class : Error< "'using namespace' in class not allowed">; +def err_ident_in_pseudo_dtor_not_a_type : Error< + "identifier %0 in pseudo-destructor expression does not name a type">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -279,6 +285,9 @@ def err_typename_refers_to_non_type_template : Error< "typename specifier refers to a non-template">; def err_expected_type_name_after_typename : Error< "expected an identifier or template-id after '::'">; +def err_explicit_spec_non_template : Error< + "explicit %select{specialization|instantiation}0 of non-template " + "%select{class|struct|union}1 %2">; def err_variadic_templates : Error< "variadic templates are only allowed in C++0x">; @@ -286,7 +295,7 @@ def err_variadic_templates : Error< // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; - + // Language specific pragmas // - Generic warnings def warn_pragma_expected_lparen : Warning< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7a87e244f77c..99fddb581088 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -264,13 +264,19 @@ def warn_objc_property_copy_missing_on_block : Warning< "'copy' attribute must be specified for the block property " "when -fobjc-gc-only is specified">; def err_use_continuation_class : Error< - "attribute of property in continuation class of %0 can only be 'readwrite'">; + "property declaration in continuation class of %0 is to change a 'readonly' " + "property to 'readwrite'">; def err_continuation_class : Error<"continuation class has no primary class">; def err_property_type : Error<"property cannot have array or function type %0">; def error_missing_property_context : Error< "missing context for property implementation declaration">; def error_bad_property_decl : Error< "property implementation must have its declaration in interface %0">; +def error_category_property : Error< + "property declared in category %0 cannot be implemented in " + "class implementation">; +def note_property_declare : Note< + "property declared here">; def error_synthesize_category_decl : Error< "@synthesize not allowed in a category's implementation">; def error_missing_property_interface : Error< @@ -613,6 +619,10 @@ def warn_attribute_wrong_decl_type : Warning< def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; +def err_cconv_knr : Error< + "function with no prototype cannot use '%0' calling convention">; +def err_cconv_varargs : Error< + "variadic function cannot use '%0' calling convention">; def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">; @@ -1014,7 +1024,11 @@ def note_partial_spec_unused_parameter : Note< def err_partial_spec_ordering_ambiguous : Error< "ambiguous partial specializations of %0">; def note_partial_spec_match : Note<"partial specialization matches %0">; - +def err_partial_spec_redeclared : Error< + "class template partial specialization %0 cannot be redeclared">; +def note_prev_partial_spec_here : Note< + "previous declaration of class template partial specialization %0 is here">; + // C++ Function template specializations def err_function_template_spec_no_match : Error< "no function template matches function template specialization %0">; @@ -1326,17 +1340,17 @@ def err_flexible_array_init_nonempty : Error< def err_flexible_array_init_needs_braces : Error< "flexible array requires brace-enclosed initializer">; def err_illegal_decl_array_of_functions : Error< - "'%0' declared as array of functions">; + "'%0' declared as array of functions of type %1">; def err_illegal_decl_array_incomplete_type : Error< "array has incomplete element type %0">; def err_illegal_decl_array_of_references : Error< - "'%0' declared as array of references">; + "'%0' declared as array of references of type %1">; def err_array_star_outside_prototype : Error< "star modifier used outside of function prototype">; def err_illegal_decl_pointer_to_reference : Error< - "'%0' declared as a pointer to a reference">; + "'%0' declared as a pointer to a reference of type %1">; def err_illegal_decl_mempointer_to_reference : Error< - "'%0' declared as a member pointer to a reference">; + "'%0' declared as a member pointer to a reference of type %1">; def err_illegal_decl_mempointer_to_void : Error< "'%0' declared as a member pointer to void">; def err_illegal_decl_mempointer_in_nonclass : Error< @@ -1368,6 +1382,8 @@ def err_alignof_incomplete_type : Error< "invalid application of '__alignof' to an incomplete type %0">; def err_sizeof_alignof_bitfield : Error< "invalid application of '%select{sizeof|__alignof}0' to bit-field">; +def err_offsetof_incomplete_type : Error< + "offsetof of incomplete type %0">; def err_offsetof_record_type : Error< "offsetof requires struct, union, or class type, %0 invalid">; def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; @@ -1385,6 +1401,10 @@ def warn_shift_negative : Warning< def warn_shift_gt_typewidth : Warning< "shift count >= width of type">; +def warn_precedence_bitwise_rel : Warning< + "%0 has lower precedence than %1; %1 will be evaluated first">, + InGroup<Parentheses>; + def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " "non-fragile ABI">; @@ -1661,7 +1681,9 @@ def err_bad_new_type : Error< def err_new_incomplete_type : Error< "allocation of incomplete type %0">; def err_new_array_nonconst : Error< - "only the first dimension of an allocated array may be non-const">; + "only the first dimension of an allocated array may have dynamic size">; +def err_new_paren_array_nonconst : Error< + "when type is in parentheses, array cannot have dynamic size">; def err_array_size_not_integral : Error< "array size expression must have integral or enumerated type, not %0">; def err_new_uninitialized_const : Error< @@ -1709,8 +1731,6 @@ def err_throw_incomplete_ptr : Error< def err_return_in_constructor_handler : Error< "return in the catch of a function try block of a constructor is illegal">; -def err_ident_in_pseudo_dtor_not_a_type : Error< - "identifier %0 in pseudo-destructor expression does not name a type">; def err_operator_arrow_circular : Error< "circular pointer delegation detected">; def err_pseudo_dtor_base_not_scalar : Error< @@ -2130,6 +2150,10 @@ def warn_ret_stack_addr : Warning< "address of stack memory associated with local variable %0 returned">; def warn_ret_stack_ref : Warning< "reference to stack memory associated with local variable %0 returned">; +def warn_ret_addr_label : Warning< + "returning address of label, which is local">; +def err_ret_local_block : Error< + "returning block that lives on the local stack">; // For non-floating point, expressions of the form x == x or x != x @@ -2153,8 +2177,6 @@ def err_return_in_block_expression : Error< def err_block_returns_array : Error< "block declared as returning an array">; -def err_ret_local_block : Error< - "returning block that lives on the local stack">; // CFString checking def err_cfstring_literal_not_string_constant : Error< diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 2184bf3c457c..6b60f2eec097 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -16,7 +16,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Host.h" diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h index 790b75ba3af3..c0a95051a72d 100644 --- a/include/clang/Basic/OperatorKinds.h +++ b/include/clang/Basic/OperatorKinds.h @@ -26,7 +26,10 @@ enum OverloadedOperatorKind { NUM_OVERLOADED_OPERATORS }; - +/// \brief Retrieve the spelling of the given overloaded operator, without +/// the preceding "operator" keyword. +const char *getOperatorSpelling(OverloadedOperatorKind Operator); + } // end namespace clang #endif diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index e8cc564c8a20..9960d5beb5c1 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -109,7 +109,7 @@ public: // Add all arguments. for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], - (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); + (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); } // Add all ranges. @@ -129,13 +129,25 @@ public: PD.AddTaggedVal(I, Diagnostic::ak_uint); return PD; } - + + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + int I) { + PD.AddTaggedVal(I, Diagnostic::ak_sint); + return PD; + } + + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const char *S) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string); + return PD; + } + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const SourceRange &R) { PD.AddSourceRange(R); return PD; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, DeclarationName N); }; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 8a69cba066b3..7e9ac531017e 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -16,7 +16,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include <vector> #include <cassert> diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index b88e2aaba383..e61ef9265cfb 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -17,7 +17,7 @@ // FIXME: Daniel isn't smart enough to use a prototype for this. #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include <cassert> #include <vector> #include <string> @@ -103,9 +103,9 @@ public: /// enum. For example, SignedInt -> getIntWidth(). unsigned getTypeWidth(IntType T) const; - /// getTypeSigned - Return whether an integer types is signed. Returns true if + /// isTypeSigned - Return whether an integer types is signed. Returns true if /// the type is signed; false otherwise. - bool getTypeSigned(IntType T) const; + bool isTypeSigned(IntType T) const; /// getPointerWidth - Return the width of pointers on this target, for the /// specified address space. diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index 4084be6c0b42..5370114ee824 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -404,6 +404,7 @@ OPTION("-flax-vector-conversions", flax_vector_conversions, Flag, f_Group, INVAL OPTION("-flimited-precision=", flimited_precision_EQ, Joined, f_Group, INVALID, "", 0, 0, 0) OPTION("-flto", flto, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fmath-errno", fmath_errno, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fmerge-all-constants", fmerge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fmessage-length=", fmessage_length_EQ, Joined, f_Group, INVALID, "", 0, 0, 0) OPTION("-fms-extensions", fms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fmudflapth", fmudflapth, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -428,6 +429,7 @@ OPTION("-fno-inline-functions", fno_inline_functions, Flag, clang_ignored_f_Grou OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -559,6 +561,7 @@ OPTION("-m", m_Joined, Joined, m_Group, INVALID, "", 0, 0, 0) OPTION("-no-cpp-precomp", no_cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, 0, 0) OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0) +OPTION("-nobuiltininc", nobuiltininc, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0) @@ -566,7 +569,6 @@ OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nostartfiles", nostartfiles, Flag, INVALID, INVALID, "", 0, 0, 0) -OPTION("-nostdclanginc", nostdclanginc, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nostdinc", nostdinc, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nostdlib", nostdlib, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-object", object, Flag, INVALID, INVALID, "", 0, 0, 0) diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 9573777b5f6f..7dfabbadd8fd 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -18,6 +18,7 @@ #include "llvm/ADT/OwningPtr.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Basic/FileManager.h" +#include "clang/Index/ASTLocation.h" #include <string> namespace clang { @@ -32,6 +33,8 @@ namespace clang { class ASTContext; class Decl; +using namespace idx; + /// \brief Utility class for loading a ASTContext from a PCH file. /// class ASTUnit { @@ -50,9 +53,11 @@ class ASTUnit { // FIXME: This is temporary; eventually, CIndex will always do this. bool OnlyLocalDecls; + // Critical optimization when using clang_getCursor(). + ASTLocation LastLoc; + ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT - ASTUnit(); public: ASTUnit(DiagnosticClient *diagClient = NULL); @@ -80,6 +85,9 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } + ASTLocation getLastASTLocation() const { return LastLoc; } + /// \brief Create a ASTUnit from a PCH file. /// /// \param Filename - The PCH file to load. diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h index 508af537b1fa..ad53a8d592ba 100644 --- a/include/clang/Frontend/CompileOptions.h +++ b/include/clang/Frontend/CompileOptions.h @@ -43,7 +43,8 @@ public: unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. - + unsigned MergeAllConstants : 1; // Merge identical constants. + /// Inlining - The kind of inlining to perform. InliningMethod Inlining; @@ -67,6 +68,7 @@ public: Inlining = NoInlining; DisableRedZone = 0; NoImplicitFloat = 0; + MergeAllConstants = 1; } }; diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index 36323c260c9a..8b80d1dc11d8 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -99,7 +99,7 @@ NODE_XML(FunctionDecl, "Function") ENUM_XML(FunctionDecl::Static, "static") ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__") END_ENUM_XML - ATTRIBUTE_OPT_XML(isInline(), "inline") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference ATTRIBUTE_XML(getNumParams(), "num_args") SUB_NODE_SEQUENCE_XML(ParmVarDecl) @@ -113,7 +113,7 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl") ATTRIBUTE_XML(getNameAsString(), "name") TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_OPT_XML(isInline(), "inline") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") ATTRIBUTE_OPT_XML(isStatic(), "static") ATTRIBUTE_OPT_XML(isVirtual(), "virtual") ATTRIBUTE_XML(getNumParams(), "num_args") diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h new file mode 100644 index 000000000000..58673e4dad6b --- /dev/null +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -0,0 +1,49 @@ +//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H +#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// DiagnosticOptions - Options for controlling the compiler diagnostics +/// engine. +class DiagnosticOptions { +public: + unsigned ShowColumn : 1; /// Show column number on diagnostics. + unsigned ShowLocation : 1; /// Show source location information. + unsigned ShowCarets : 1; /// Show carets in diagnostics. + unsigned ShowFixits : 1; /// Show fixit information. + unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. + unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable + /// diagnostics. + unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. + + /// Column limit for formatting message diagnostics, or 0 if unused. + unsigned MessageLength; + +public: + DiagnosticOptions() { + ShowColumn = 1; + ShowLocation = 1; + ShowCarets = 1; + ShowFixits = 1; + ShowSourceRanges = 0; + ShowOptionNames = 0; + ShowColors = 0; + MessageLength = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/InitHeaderSearch.h b/include/clang/Frontend/InitHeaderSearch.h index a90b4eaf9e2b..48c426825262 100644 --- a/include/clang/Frontend/InitHeaderSearch.h +++ b/include/clang/Frontend/InitHeaderSearch.h @@ -73,6 +73,16 @@ public: /// variables such as CPATH. void AddDefaultEnvVarPaths(const LangOptions &Lang); + // AddDefaultCIncludePaths - Add paths that should always be searched. + void AddDefaultCIncludePaths(const llvm::Triple &triple); + + // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when + // compiling c++. + void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple); + + // AddDefaultFrameworkIncludePaths - Add the framework paths. Used on darwin. + void AddDefaultFrameworkIncludePaths(const llvm::Triple &triple); + /// AddDefaultSystemIncludePaths - Adds the default system include paths so /// that e.g. stdio.h is found. void AddDefaultSystemIncludePaths(const LangOptions &Lang, diff --git a/include/clang/Frontend/InitPreprocessor.h b/include/clang/Frontend/InitPreprocessor.h index eb03602dc57b..b29ee2728a86 100644 --- a/include/clang/Frontend/InitPreprocessor.h +++ b/include/clang/Frontend/InitPreprocessor.h @@ -63,7 +63,8 @@ public: /// environment ready to process a single file. This returns true on error. /// bool InitializePreprocessor(Preprocessor &PP, - const PreprocessorInitOptions& InitOptions); + const PreprocessorInitOptions& InitOptions, + bool undef_macros); } // end namespace clang diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 1e953d671226..b2bb9a13771d 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -18,7 +18,7 @@ #define LLVM_CLANG_FRONTEND_PCHBITCODES_H #include "llvm/Bitcode/BitCodes.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" namespace clang { namespace pch { @@ -496,8 +496,6 @@ namespace clang { DECL_IMPLICIT_PARAM, /// \brief A ParmVarDecl record. DECL_PARM_VAR, - /// \brief An OriginalParmVarDecl record. - DECL_ORIGINAL_PARM_VAR, /// \brief A FileScopeAsmDecl record. DECL_FILE_SCOPE_ASM, /// \brief A BlockDecl record. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index cc16970b0040..cc8b3a03e3e8 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -19,6 +19,7 @@ #include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Type.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" @@ -29,7 +30,7 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include <deque> #include <map> #include <string> @@ -542,6 +543,12 @@ public: /// comments in the source code. virtual void ReadComments(std::vector<SourceRange> &Comments); + /// \brief Reads a TemplateArgumentLocInfo appropriate for the + /// given TemplateArgument kind. + TemplateArgumentLocInfo + GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + const RecordData &Record, unsigned &Idx); + /// \brief Reads a declarator info from the given record. virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record, unsigned &Idx); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 728e138d9e7c..22427eb67103 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -275,6 +275,10 @@ public: /// \brief Emits a reference to a declarator info. void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record); + /// \brief Emits a template argument location. + void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, + RecordData &Record); + /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordData &Record); diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 0fd8d44f72bc..98e5a75c65b9 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -23,42 +23,21 @@ namespace llvm { } namespace clang { -class SourceManager; +class DiagnosticOptions; class LangOptions; +class SourceManager; class TextDiagnosticPrinter : public DiagnosticClient { llvm::raw_ostream &OS; const LangOptions *LangOpts; + const DiagnosticOptions *DiagOpts; + SourceLocation LastWarningLoc; FullSourceLoc LastLoc; bool LastCaretDiagnosticWasNote; - bool ShowColumn; - bool CaretDiagnostics; - bool ShowLocation; - bool PrintRangeInfo; - bool PrintDiagnosticOption; - bool PrintFixItInfo; - unsigned MessageLength; - bool UseColors; - public: - TextDiagnosticPrinter(llvm::raw_ostream &os, - bool showColumn = true, - bool caretDiagnistics = true, bool showLocation = true, - bool printRangeInfo = true, - bool printDiagnosticOption = true, - bool printFixItInfo = true, - unsigned messageLength = 0, - bool useColors = false) - : OS(os), LangOpts(0), - LastCaretDiagnosticWasNote(false), ShowColumn(showColumn), - CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation), - PrintRangeInfo(printRangeInfo), - PrintDiagnosticOption(printDiagnosticOption), - PrintFixItInfo(printFixItInfo), - MessageLength(messageLength), - UseColors(useColors) {} + TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags); void setLangOptions(const LangOptions *LO) { LangOpts = LO; diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h index 36cf56dea203..f8e01f728648 100644 --- a/include/clang/Index/Utils.h +++ b/include/clang/Index/Utils.h @@ -18,7 +18,6 @@ namespace clang { class ASTContext; class SourceLocation; - class Decl; namespace idx { class ASTLocation; @@ -28,7 +27,7 @@ namespace idx { /// \returns the resolved ASTLocation or an invalid ASTLocation if the source /// location could not be resolved. ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc, - Decl *RelativeToDecl = 0); + ASTLocation *LastLoc = 0); } // end namespace idx diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 97656f7d39d6..c4ab5aebf721 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -17,7 +17,7 @@ #include <string> #include "llvm/ADT/SmallString.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" namespace llvm { class APInt; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 0765ac391be3..35960ff328a6 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -75,6 +75,8 @@ class Preprocessor { IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_builtin; // __has_builtin + IdentifierInfo *Ident__has_include; // __has_include + IdentifierInfo *Ident__has_include_next; // __has_include_next SourceLocation DATELoc, TIMELoc; unsigned CounterValue; // Next __COUNTER__ value. @@ -244,7 +246,12 @@ public: return CurPPLexer == L; } - /// getCurrentLexer - Return the current file lexer being lexed from. Note + /// getCurrentLexer - Return the current lexer being lexed from. Note + /// that this ignores any potentially active macro expansions and _Pragma + /// expansions going on at the time. + PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; } + + /// getCurrentFileLexer - Return the current file lexer being lexed from. Note /// that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; @@ -622,6 +629,43 @@ public: /// SourceLocation. MacroInfo* AllocateMacroInfo(SourceLocation L); + /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully + /// checked and spelled filename, e.g. as an operand of #include. This returns + /// true if the input filename was in <>'s or false if it were in ""'s. The + /// caller is expected to provide a buffer that is large enough to hold the + /// spelling of the filename, but is also expected to handle the case when + /// this method decides to use a different buffer. + bool GetIncludeFilenameSpelling(SourceLocation Loc, + const char *&BufStart, const char *&BufEnd); + + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, + /// return null on failure. isAngled indicates whether the file reference is + /// for system #include's or not (i.e. using <> instead of ""). + const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd, + bool isAngled, const DirectoryLookup *FromDir, + const DirectoryLookup *&CurDir); + + /// GetCurLookup - The DirectoryLookup structure used to find the current + /// FileEntry, if CurLexer is non-null and if applicable. This allows us to + /// implement #include_next and find directory-specific properties. + const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } + + /// isInPrimaryFile - Return true if we're in the top-level file, not in a + /// #include. + bool isInPrimaryFile() const; + + /// ConcatenateIncludeName - Handle cases where the #include name is expanded + /// from a macro as multiple tokens, which need to be glued together. This + /// occurs for code like: + /// #define FOO <a/b.h> + /// #include FOO + /// because in this case, "<a/b.h>" is returned as 7 tokens, not one. + /// + /// This code concatenates and consumes tokens up to the '>' token. It returns + /// false if the > was found, otherwise it returns true if it finds and consumes + /// the EOM marker. + bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer); + private: void PushIncludeMacroStack() { @@ -646,10 +690,6 @@ private: /// be reused for allocating new MacroInfo objects. void ReleaseMacroInfo(MacroInfo* MI); - /// isInPrimaryFile - Return true if we're in the top-level file, not in a - /// #include. - bool isInPrimaryFile() const; - /// ReadMacroName - Lex and validate a macro name, which occurs after a /// #define or #undef. This emits a diagnostic, sets the token kind to eom, /// and discards the rest of the macro line if the macro name is invalid. @@ -722,24 +762,6 @@ private: /// start getting tokens from it using the PTH cache. void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); - /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully - /// checked and spelled filename, e.g. as an operand of #include. This returns - /// true if the input filename was in <>'s or false if it were in ""'s. The - /// caller is expected to provide a buffer that is large enough to hold the - /// spelling of the filename, but is also expected to handle the case when - /// this method decides to use a different buffer. - bool GetIncludeFilenameSpelling(SourceLocation Loc, - const char *&BufStart, const char *&BufEnd); - - /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, - /// return null on failure. isAngled indicates whether the file reference is - /// for system #include's or not (i.e. using <> instead of ""). - const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd, - bool isAngled, const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir); - - - /// IsFileLexer - Returns true if we are lexing from a file and not a /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 8acdb30cc705..8d910959b9fa 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -17,6 +17,7 @@ #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/OperatorKinds.h" #include <cstdlib> namespace clang { @@ -62,12 +63,12 @@ class Token { /// Kind - The actual flavor of token this is. /// - unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind'; + unsigned char Kind; // DON'T make Kind a 'tok::TokenKind'; // MSVC will treat it as a signed char and // TokenKinds > 127 won't be handled correctly. /// Flags - Bits we track about this token, members of the TokenFlags enum. - unsigned Flags : 8; + unsigned char Flags; public: // Various flags set per token: @@ -261,6 +262,9 @@ struct TemplateIdAnnotation { /// FIXME: Temporarily stores the name of a specialization IdentifierInfo *Name; + /// FIXME: Temporarily stores the overloaded operator kind. + OverloadedOperatorKind Operator; + /// The declaration of the template corresponding to the /// template-name. This is an Action::DeclTy*. void *Template; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 050b3f42e4cd..073365dcede3 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -161,6 +161,23 @@ public: // Declaration Tracking Callbacks. //===--------------------------------------------------------------------===// + typedef uintptr_t ParsingDeclStackState; + + /// PushParsingDeclaration - Notes that the parser has begun + /// processing a declaration of some sort. Guaranteed to be matched + /// by a call to PopParsingDeclaration with the value returned by + /// this method. + virtual ParsingDeclStackState PushParsingDeclaration() { + return ParsingDeclStackState(); + } + + /// PopParsingDeclaration - Notes that the parser has completed + /// processing a declaration of some sort. The decl will be empty + /// if the declaration didn't correspond to a full declaration (or + /// if the actions module returned an empty decl for it). + virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) { + } + /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it /// needs a decl group, it calls this to convert between the two /// representations. @@ -236,30 +253,36 @@ public: virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = 0) = 0; - /// \brief Determine whether the given identifier refers to the name of a + /// \brief Determine whether the given name refers to a template. + /// + /// This callback is used by the parser after it has seen a '<' to determine + /// whether the given name refers to a template and, if so, what kind of /// template. /// - /// \param S the scope in which name lookup occurs + /// \param S the scope in which the name occurs. /// - /// \param II the identifier that we are querying to determine whether it - /// is a template. + /// \param SS the C++ nested-name-specifier that precedes the template name, + /// if any. /// - /// \param IdLoc the source location of the identifier + /// \param Name the name that we are querying to determine whether it is + /// a template. /// - /// \param SS the C++ scope specifier that precedes the template name, if - /// any. + /// \param ObjectType if we are determining whether the given name is a + /// template name in the context of a member access expression (e.g., + /// \c p->X<int>), this is the type of the object referred to by the + /// member access (e.g., \c p). /// /// \param EnteringContext whether we are potentially entering the context - /// referred to by the scope specifier \p SS + /// referred to by the nested-name-specifier \p SS, which allows semantic + /// analysis to look into uninstantiated templates. /// /// \param Template if the name does refer to a template, the declaration /// of the template that the name refers to. /// /// \returns the kind of template that this name refers to. virtual TemplateNameKind isTemplateName(Scope *S, - const IdentifierInfo &II, - SourceLocation IdLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, TemplateTy &Template) = 0; @@ -854,47 +877,33 @@ public: virtual SourceRange getExprRange(ExprTy *E) const { return SourceRange(); } - - /// ActOnIdentifierExpr - Parse an identifier in expression context. - /// 'HasTrailingLParen' indicates whether or not the identifier has a '(' - /// token immediately after it. - /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or - /// namespace) that the identifier must be a member of. - /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::". - virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen, - const CXXScopeSpec *SS = 0, - bool isAddressOfOperand = false){ - return ExprEmpty(); - } - - /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator - /// name (e.g., @c operator+ ) as an expression. This is very - /// similar to ActOnIdentifierExpr, except that instead of providing - /// an identifier the parser provides the kind of overloaded - /// operator that was parsed. - virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr( - Scope *S, SourceLocation OperatorLoc, - OverloadedOperatorKind Op, - bool HasTrailingLParen, const CXXScopeSpec &SS, - bool isAddressOfOperand = false) { - return ExprEmpty(); - } - - /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function - /// name (e.g., @c operator void const *) as an expression. This is - /// very similar to ActOnIdentifierExpr, except that instead of - /// providing an identifier the parser provides the type of the - /// conversion function. - virtual OwningExprResult ActOnCXXConversionFunctionExpr( - Scope *S, SourceLocation OperatorLoc, - TypeTy *Type, bool HasTrailingLParen, - const CXXScopeSpec &SS, - bool isAddressOfOperand = false) { + + /// \brief Parsed an id-expression (C++) or identifier (C) in expression + /// context, e.g., the expression "x" that refers to a variable named "x". + /// + /// \param S the scope in which this id-expression or identifier occurs. + /// + /// \param SS the C++ nested-name-specifier that qualifies the name of the + /// value, e.g., "std::" in "std::sort". + /// + /// \param Name the name to which the id-expression refers. In C, this will + /// always be an identifier. In C++, it may also be an overloaded operator, + /// destructor name (if there is a nested-name-specifier), or template-id. + /// + /// \param HasTrailingLParen whether the next token following the + /// id-expression or identifier is a left parentheses ('('). + /// + /// \param IsAddressOfOperand whether the token that precedes this + /// id-expression or identifier was an ampersand ('&'), indicating that + /// we will be taking the address of this expression. + virtual OwningExprResult ActOnIdExpression(Scope *S, + const CXXScopeSpec &SS, + UnqualifiedId &Name, + bool HasTrailingLParen, + bool IsAddressOfOperand) { return ExprEmpty(); } - + virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { return ExprEmpty(); @@ -936,16 +945,42 @@ public: SourceLocation RLoc) { return ExprEmpty(); } - virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - IdentifierInfo &Member, - DeclPtrTy ObjCImpDecl, - const CXXScopeSpec *SS = 0) { + + /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref]) + /// of the form \c x.m or \c p->m. + /// + /// \param S the scope in which the member access expression occurs. + /// + /// \param Base the class or pointer to class into which this member + /// access expression refers, e.g., \c x in \c x.m. + /// + /// \param OpLoc the location of the "." or "->" operator. + /// + /// \param OpKind the kind of member access operator, which will be either + /// tok::arrow ("->") or tok::period ("."). + /// + /// \param SS in C++, the nested-name-specifier that precedes the member + /// name, if any. + /// + /// \param Member the name of the member that we are referring to. In C, + /// this will always store an identifier; in C++, we may also have operator + /// names, conversion function names, destructors, and template names. + /// + /// \param ObjCImpDecl the Objective-C implementation declaration. + /// FIXME: Do we really need this? + /// + /// \param HasTrailingLParen whether this member name is immediately followed + /// by a left parentheses ('('). + virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + UnqualifiedId &Member, + DeclPtrTy ObjCImpDecl, + bool HasTrailingLParen) { return ExprEmpty(); } - + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. There are guaranteed to be one fewer commas than arguments, @@ -1245,8 +1280,7 @@ public: } /// ActOnFriendTypeDecl - Parsed a friend type declaration. - virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, - const DeclSpec &DS, + virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TParams) { return DeclPtrTy(); } @@ -1376,123 +1410,6 @@ public: return ExprEmpty(); } - /// ActOnDestructorReferenceExpr - Parsed a destructor reference, for example: - /// - /// t->~T(); - virtual OwningExprResult - ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - IdentifierInfo *ClassName, - const CXXScopeSpec &SS, - bool HasTrailingLParen) { - 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: - /// - /// t.operator++(); - virtual OwningExprResult - ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - OverloadedOperatorKind OverOpKind, - const CXXScopeSpec *SS = 0) { - return ExprEmpty(); - } - - /// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion - /// function reference, for example: - /// - /// t.operator int(); - virtual OwningExprResult - ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - TypeTy *Ty, - const CXXScopeSpec *SS = 0) { - return ExprEmpty(); - } - - /// \brief Parsed a reference to a member template-id. - /// - /// This callback will occur instead of ActOnMemberReferenceExpr() when the - /// member in question is a template for which the code provides an - /// explicitly-specified template argument list, e.g., - /// - /// \code - /// x.f<int>() - /// \endcode - /// - /// \param S the scope in which the member reference expression occurs - /// - /// \param Base the expression to the left of the "." or "->". - /// - /// \param OpLoc the location of the "." or "->". - /// - /// \param OpKind the kind of operator, which will be "." or "->". - /// - /// \param SS the scope specifier that precedes the template-id in, e.g., - /// \c x.Base::f<int>(). - /// - /// \param Template the declaration of the template that is being referenced. - /// - /// \param TemplateNameLoc the location of the template name referred to by - /// \p Template. - /// - /// \param LAngleLoc the location of the left angle bracket ('<') - /// - /// \param TemplateArgs the (possibly-empty) template argument list provided - /// as part of the member reference. - /// - /// \param RAngleLoc the location of the right angle bracket ('>') - virtual OwningExprResult - ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - // FIXME: "template" keyword? - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc) { - return ExprEmpty(); - } - /// ActOnFinishFullExpr - Called whenever a full expression has been parsed. /// (C++ [intro.execution]p12). virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) { @@ -1712,40 +1629,6 @@ public: return TypeResult(); } - /// \brief Form a reference to a template-id (that will refer to a function) - /// from a template and a list of template arguments. - /// - /// This action forms an expression that references the given template-id, - /// 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. - /// - /// \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, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc) { - return ExprError(); - } - /// \brief Form a dependent template name. /// /// This action forms a dependent template name given the template @@ -1756,22 +1639,19 @@ public: /// /// \param TemplateKWLoc the location of the "template" keyword (if any). /// - /// \param Name the name of the template (an identifier) - /// - /// \param NameLoc the location of the identifier - /// /// \param SS the nested-name-specifier that precedes the "template" keyword - /// or the template name. FIXME: If the dependent template name occurs in + /// or the template name. If the dependent template name occurs in /// a member access expression, e.g., "x.template f<T>", this /// nested-name-specifier will be empty. /// + /// \param Name the name of the template. + /// /// \param ObjectType if this dependent template name occurs in the /// context of a member access expression, the type of the object being /// accessed. virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - const IdentifierInfo &Name, - SourceLocation NameLoc, const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType) { return TemplateTy(); } @@ -2473,13 +2353,12 @@ public: const CXXScopeSpec *SS); virtual TemplateNameKind isTemplateName(Scope *S, - const IdentifierInfo &II, - SourceLocation IdLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, TemplateTy &Template); - + /// ActOnDeclarator - If this is a typedef declarator, we modify the /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 51970f1867d9..dccb8bcfeb9a 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -390,17 +390,20 @@ public: }; - ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), - GetterName(0), SetterName(0) { } + ObjCDeclSpec() + : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), + GetterName(0), SetterName(0) { } ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } - void setObjCDeclQualifier(ObjCDeclQualifier DQVal) - { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } + void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { + objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); + } - ObjCPropertyAttributeKind getPropertyAttributes() const - { return ObjCPropertyAttributeKind(PropertyAttributes); } + ObjCPropertyAttributeKind getPropertyAttributes() const { + return ObjCPropertyAttributeKind(PropertyAttributes); + } void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { PropertyAttributes = - (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal); + (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal); } const IdentifierInfo *getGetterName() const { return GetterName; } @@ -456,6 +459,193 @@ public: } }; +/// \brief Represents a C++ unqualified-id that has been parsed. +class UnqualifiedId { +private: + const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT + +public: + /// \brief Describes the kind of unqualified-id parsed. + enum IdKind { + /// \brief An identifier. + IK_Identifier, + /// \brief An overloaded operator name, e.g., operator+. + IK_OperatorFunctionId, + /// \brief A conversion function name, e.g., operator int. + IK_ConversionFunctionId, + /// \brief A constructor name. + IK_ConstructorName, + /// \brief A destructor name. + IK_DestructorName, + /// \brief A template-id, e.g., f<int>. + IK_TemplateId + } Kind; + + /// \brief Anonymous union that holds extra data associated with the + /// parsed unqualified-id. + union { + /// \brief When Kind == IK_Identifier, the parsed identifier. + IdentifierInfo *Identifier; + + /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator + /// that we parsed. + struct { + /// \brief The kind of overloaded operator. + OverloadedOperatorKind Operator; + + /// \brief The source locations of the individual tokens that name + /// the operator, e.g., the "new", "[", and "]" tokens in + /// operator new []. + /// + /// Different operators have different numbers of tokens in their name, + /// up to three. Any remaining source locations in this array will be + /// set to an invalid value for operators with fewer than three tokens. + unsigned SymbolLocations[3]; + } OperatorFunctionId; + + /// \brief When Kind == IK_ConversionFunctionId, the type that the + /// conversion function names. + ActionBase::TypeTy *ConversionFunctionId; + + /// \brief When Kind == IK_ConstructorName, the class-name of the type + /// whose constructor is being referenced. + ActionBase::TypeTy *ConstructorName; + + /// \brief When Kind == IK_DestructorName, the type referred to by the + /// class-name. + ActionBase::TypeTy *DestructorName; + + /// \brief When Kind == IK_TemplateId, the template-id annotation that + /// contains the template name and template arguments. + TemplateIdAnnotation *TemplateId; + }; + + /// \brief The location of the first token that describes this unqualified-id, + /// which will be the location of the identifier, "operator" keyword, + /// tilde (for a destructor), or the template name of a template-id. + SourceLocation StartLocation; + + /// \brief The location of the last token that describes this unqualified-id. + SourceLocation EndLocation; + + UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { } + + /// \brief Do not use this copy constructor. It is temporary, and only + /// exists because we are holding FieldDeclarators in a SmallVector when we + /// don't actually need them. + /// + /// FIXME: Kill this copy constructor. + UnqualifiedId(const UnqualifiedId &Other) + : Kind(IK_Identifier), Identifier(Other.Identifier), + StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) { + assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers"); + } + + /// \brief Destroy this unqualified-id. + ~UnqualifiedId() { clear(); } + + /// \brief Clear out this unqualified-id, setting it to default (invalid) + /// state. + void clear(); + + /// \brief Determine whether this unqualified-id refers to a valid name. + bool isValid() const { return StartLocation.isValid(); } + + /// \brief Determine whether this unqualified-id refers to an invalid name. + bool isInvalid() const { return !isValid(); } + + /// \brief Determine what kind of name we have. + IdKind getKind() const { return Kind; } + + /// \brief Specify that this unqualified-id was parsed as an identifier. + /// + /// \param Id the parsed identifier. + /// \param IdLoc the location of the parsed identifier. + void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) { + Kind = IK_Identifier; + Identifier = const_cast<IdentifierInfo *>(Id); + StartLocation = EndLocation = IdLoc; + } + + /// \brief Specify that this unqualified-id was parsed as an + /// operator-function-id. + /// + /// \param OperatorLoc the location of the 'operator' keyword. + /// + /// \param Op the overloaded operator. + /// + /// \param SymbolLocations the locations of the individual operator symbols + /// in the operator. + void setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]); + + /// \brief Specify that this unqualified-id was parsed as a + /// conversion-function-id. + /// + /// \param OperatorLoc the location of the 'operator' keyword. + /// + /// \param Ty the type to which this conversion function is converting. + /// + /// \param EndLoc the location of the last token that makes up the type name. + void setConversionFunctionId(SourceLocation OperatorLoc, + ActionBase::TypeTy *Ty, + SourceLocation EndLoc) { + Kind = IK_ConversionFunctionId; + StartLocation = OperatorLoc; + EndLocation = EndLoc; + ConversionFunctionId = Ty; + } + + /// \brief Specify that this unqualified-id was parsed as a constructor name. + /// + /// \param ClassType the class type referred to by the constructor name. + /// + /// \param ClassNameLoc the location of the class name. + /// + /// \param EndLoc the location of the last token that makes up the type name. + void setConstructorName(ActionBase::TypeTy *ClassType, + SourceLocation ClassNameLoc, + SourceLocation EndLoc) { + Kind = IK_ConstructorName; + StartLocation = ClassNameLoc; + EndLocation = EndLoc; + ConstructorName = ClassType; + } + + /// \brief Specify that this unqualified-id was parsed as a destructor name. + /// + /// \param TildeLoc the location of the '~' that introduces the destructor + /// name. + /// + /// \param ClassType the name of the class referred to by the destructor name. + void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType, + SourceLocation EndLoc) { + Kind = IK_DestructorName; + StartLocation = TildeLoc; + EndLocation = EndLoc; + DestructorName = ClassType; + } + + /// \brief Specify that this unqualified-id was parsed as a template-id. + /// + /// \param TemplateId the template-id annotation that describes the parsed + /// template-id. This UnqualifiedId instance will take ownership of the + /// \p TemplateId and will free it on destruction. + void setTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_TemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; + } + + /// \brief Return the source range that covers this unqualified-id. + SourceRange getSourceRange() const { + return SourceRange(StartLocation, EndLocation); + } +}; + /// CachedTokens - A set of tokens that has been cached for later /// parsing. typedef llvm::SmallVector<Token, 4> CachedTokens; @@ -790,33 +980,16 @@ public: BlockLiteralContext // Block literal declarator. }; - /// DeclaratorKind - The kind of declarator this represents. - enum DeclaratorKind { - DK_Abstract, // An abstract declarator (has no identifier) - DK_Normal, // A normal declarator (has an identifier). - DK_Constructor, // A C++ constructor (identifier is the class name) - DK_Destructor, // A C++ destructor (identifier is ~class name) - DK_Operator, // A C++ overloaded operator name - DK_Conversion, // A C++ conversion function (identifier is - // "operator " then the type name) - DK_TemplateId // A C++ template-id naming a function template - // specialization. - }; - private: const DeclSpec &DS; CXXScopeSpec SS; - IdentifierInfo *Identifier; - SourceLocation IdentifierLoc; + UnqualifiedId Name; SourceRange Range; /// Context - Where we are parsing this declarator. /// TheContext Context; - /// Kind - What kind of declarator this is. - DeclaratorKind Kind; - /// DeclTypeInfo - This holds each type that the declarator includes as it is /// parsed. This is pushed from the identifier out, which means that element /// #0 will be the most closely bound to the identifier, and @@ -835,21 +1008,6 @@ private: /// AsmLabel - The asm label, if specified. ActionBase::ExprTy *AsmLabel; - union { - // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the - // type associated with the constructor, destructor, or conversion - // operator. - ActionBase::TypeTy *Type; - - /// When Kind is DK_Operator, this is the actual overloaded - /// operator that this declarator names. - OverloadedOperatorKind OperatorKind; - - /// When Kind is DK_TemplateId, this is the template-id annotation that - /// contains the template and its template arguments. - TemplateIdAnnotation *TemplateId; - }; - /// InlineParams - This is a local array used for the first function decl /// chunk to avoid going to the heap for the common case when we have one /// function chunk in the declarator. @@ -863,10 +1021,9 @@ private: public: Declarator(const DeclSpec &ds, TheContext C) - : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C), - Kind(DK_Abstract), + : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), - GroupingParens(false), AttrList(0), AsmLabel(0), Type(0), + GroupingParens(false), AttrList(0), AsmLabel(0), InlineParamsUsed(false), Extension(false) { } @@ -890,8 +1047,10 @@ public: const CXXScopeSpec &getCXXScopeSpec() const { return SS; } CXXScopeSpec &getCXXScopeSpec() { return SS; } + /// \brief Retrieve the name specified by this declarator. + UnqualifiedId &getName() { return Name; } + TheContext getContext() const { return Context; } - DeclaratorKind getKind() const { return Kind; } /// getSourceRange - Get the source range that spans this declarator. const SourceRange &getSourceRange() const { return Range; } @@ -922,22 +1081,15 @@ public: /// clear - Reset the contents of this Declarator. void clear() { SS.clear(); - Identifier = 0; - IdentifierLoc = SourceLocation(); + Name.clear(); Range = DS.getSourceRange(); - if (Kind == DK_TemplateId) - TemplateId->Destroy(); - - Kind = DK_Abstract; - for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); delete AttrList; AttrList = 0; AsmLabel = 0; - Type = 0; InlineParamsUsed = false; } @@ -968,84 +1120,28 @@ public: /// isPastIdentifier - Return true if we have parsed beyond the point where /// the - bool isPastIdentifier() const { return IdentifierLoc.isValid(); } + bool isPastIdentifier() const { return Name.isValid(); } /// hasName - Whether this declarator has a name, which might be an /// identifier (accessible via getIdentifier()) or some kind of /// special C++ name (constructor, destructor, etc.). - bool hasName() const { return getKind() != DK_Abstract; } - - IdentifierInfo *getIdentifier() const { return Identifier; } - SourceLocation getIdentifierLoc() const { return IdentifierLoc; } - - void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) { - Identifier = ID; - IdentifierLoc = Loc; - if (ID) - Kind = DK_Normal; - else - Kind = DK_Abstract; - SetRangeEnd(Loc); - } - - /// setConstructor - Set this declarator to be a C++ constructor - /// declarator. Also extends the range. - void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) { - IdentifierLoc = Loc; - Kind = DK_Constructor; - Type = Ty; - SetRangeEnd(Loc); - } - - /// setDestructor - Set this declarator to be a C++ destructor - /// declarator. Also extends the range to End, which should be the identifier - /// token. - void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc, - SourceLocation EndLoc) { - IdentifierLoc = Loc; - Kind = DK_Destructor; - Type = Ty; - if (!EndLoc.isInvalid()) - SetRangeEnd(EndLoc); - } - - /// setConversionFunction - Set this declarator to be a C++ - /// conversion function declarator (e.g., @c operator int const *). - /// Also extends the range to EndLoc, which should be the last token of the - /// type name. - void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc, - SourceLocation EndLoc) { - Identifier = 0; - IdentifierLoc = Loc; - Kind = DK_Conversion; - Type = Ty; - if (!EndLoc.isInvalid()) - SetRangeEnd(EndLoc); + bool hasName() const { + return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier; } - /// setOverloadedOperator - Set this declaration to be a C++ - /// overloaded operator declarator (e.g., @c operator+). - /// Also extends the range to EndLoc, which should be the last token of the - /// operator. - void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc, - SourceLocation EndLoc) { - IdentifierLoc = Loc; - Kind = DK_Operator; - OperatorKind = Op; - if (!EndLoc.isInvalid()) - SetRangeEnd(EndLoc); + IdentifierInfo *getIdentifier() const { + if (Name.getKind() == UnqualifiedId::IK_Identifier) + return Name.Identifier; + + return 0; } + SourceLocation getIdentifierLoc() const { return Name.StartLocation; } - /// \brief Set this declaration to be a C++ template-id, which includes the - /// template (or set of function templates) along with template arguments. - void setTemplateId(TemplateIdAnnotation *TemplateId) { - assert(TemplateId && "NULL template-id provided to declarator?"); - IdentifierLoc = TemplateId->TemplateNameLoc; - Kind = DK_TemplateId; - SetRangeEnd(TemplateId->RAngleLoc); - this->TemplateId = TemplateId; + /// \brief Set the name of this declarator to be the given identifier. + void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) { + Name.setIdentifier(Id, IdLoc); } - + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { @@ -1069,6 +1165,13 @@ public: return DeclTypeInfo[i]; } + void DropFirstTypeObject() + { + assert(!DeclTypeInfo.empty() && "No type chunks to drop."); + DeclTypeInfo.front().destroy(); + DeclTypeInfo.erase(DeclTypeInfo.begin()); + } + /// isFunctionDeclarator - Once this declarator is fully parsed and formed, /// this method returns true if the identifier is a function declarator. bool isFunctionDeclarator() const { @@ -1108,22 +1211,6 @@ public: void setExtension(bool Val = true) { Extension = Val; } bool getExtension() const { return Extension; } - ActionBase::TypeTy *getDeclaratorIdType() const { - assert((Kind == DK_Constructor || Kind == DK_Destructor || - Kind == DK_Conversion) && "Declarator kind does not have a type"); - return Type; - } - - OverloadedOperatorKind getOverloadedOperator() const { - assert(Kind == DK_Operator && "Declarator is not an overloaded operator"); - return OperatorKind; - } - - TemplateIdAnnotation *getTemplateId() { - assert(Kind == DK_TemplateId && "Declarator is not a template-id"); - return TemplateId; - } - void setInvalidType(bool Val = true) { InvalidType = Val; } bool isInvalidType() const { return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; @@ -1142,7 +1229,7 @@ struct FieldDeclarator { BitfieldSize = 0; } }; - + } // end namespace clang #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 9cb4677f6637..f34d469d9823 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -571,6 +571,99 @@ private: return *ClassStack.top(); } + /// \brief RAII object used to inform the actions that we're + /// currently parsing a declaration. This is active when parsing a + /// variable's initializer, but not when parsing the body of a + /// class or function definition. + class ParsingDeclRAIIObject { + Action &Actions; + Action::ParsingDeclStackState State; + bool Popped; + + public: + ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) { + push(); + } + + ~ParsingDeclRAIIObject() { + abort(); + } + + /// Resets the RAII object for a new declaration. + void reset() { + abort(); + push(); + } + + /// Signals that the context was completed without an appropriate + /// declaration being parsed. + void abort() { + pop(DeclPtrTy()); + } + + void complete(DeclPtrTy D) { + assert(!Popped && "ParsingDeclaration has already been popped!"); + pop(D); + } + + private: + void push() { + State = Actions.PushParsingDeclaration(); + Popped = false; + } + + void pop(DeclPtrTy D) { + if (!Popped) { + Actions.PopParsingDeclaration(State, D); + Popped = true; + } + } + }; + + /// A class for parsing a DeclSpec. + class ParsingDeclSpec : public DeclSpec { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclSpec(Parser &P) : ParsingRAII(P) { + } + + void complete(DeclPtrTy D) { + ParsingRAII.complete(D); + } + + void abort() { + ParsingRAII.abort(); + } + }; + + /// A class for parsing a declarator. + class ParsingDeclarator : public Declarator { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) + : Declarator(DS, C), ParsingRAII(P) { + } + + const ParsingDeclSpec &getDeclSpec() const { + return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); + } + + ParsingDeclSpec &getMutableDeclSpec() const { + return const_cast<ParsingDeclSpec&>(getDeclSpec()); + } + + void clear() { + Declarator::clear(); + ParsingRAII.reset(); + } + + void complete(DeclPtrTy D) { + ParsingRAII.complete(D); + } + }; + /// \brief RAII object used to class ParsingClassDefinition { Parser &P; @@ -603,14 +696,17 @@ private: : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { } ParsedTemplateInfo(TemplateParameterLists *TemplateParams, - bool isSpecialization) + bool isSpecialization, + bool lastParameterListWasEmpty = false) : Kind(isSpecialization? ExplicitSpecialization : Template), - TemplateParams(TemplateParams) { } + TemplateParams(TemplateParams), + LastParameterListWasEmpty(lastParameterListWasEmpty) { } explicit ParsedTemplateInfo(SourceLocation ExternLoc, SourceLocation TemplateLoc) : Kind(ExplicitInstantiation), TemplateParams(0), - ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { } + ExternLoc(ExternLoc), TemplateLoc(TemplateLoc), + LastParameterListWasEmpty(false){ } /// \brief The kind of template we are parsing. enum { @@ -635,6 +731,9 @@ private: /// \brief The location of the 'template' keyword, for an explicit /// instantiation. SourceLocation TemplateLoc; + + /// \brief Whether the last template parameter list was empty. + bool LastParameterListWasEmpty; }; void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass); @@ -658,7 +757,7 @@ private: DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( AccessSpecifier AS = AS_none); - DeclPtrTy ParseFunctionDefinition(Declarator &D, + DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); void ParseKNRParamDeclarations(Declarator &D); // EndLoc, if non-NULL, is filled with the location of the last token of @@ -944,11 +1043,12 @@ private: DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd); DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, - SourceLocation &DeclEnd, - bool RequireSemi = true); + SourceLocation &DeclEnd); + DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, + bool AllowFunctionDefinitions, + SourceLocation *DeclEnd = 0); DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl); @@ -973,8 +1073,16 @@ private: void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); - void ParseStructDeclaration(DeclSpec &DS, - llvm::SmallVectorImpl<FieldDeclarator> &Fields); + + struct FieldCallback { + virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0; + virtual ~FieldCallback() {} + + private: + virtual void _anchor(); + }; + + void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback); bool isDeclarationSpecifier(); bool isTypeSpecifierQualifier(); @@ -1197,6 +1305,21 @@ private: BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl); AccessSpecifier getAccessSpecifierIfPresent() const; + bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Id); + bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Result); + bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, + bool AllowDestructorName, + bool AllowConstructorName, + TypeTy *ObjectType, + UnqualifiedId &Result); + //===--------------------------------------------------------------------===// // C++ 13.5: Overloaded operators [over.oper] // EndLoc, if non-NULL, is filled with the location of the last token of @@ -1247,6 +1370,7 @@ private: bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, const CXXScopeSpec *SS, + UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index d2f509df7b2c..5b3522c9eb49 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -26,6 +26,7 @@ namespace clang { class FunctionDecl; class FunctionType; class FunctionTemplateDecl; +class IdentifierInfo; class NamedDecl; class NestedNameSpecifier; class Sema; @@ -150,7 +151,8 @@ public: /// \brief Describes the kind of result generated. enum ResultKind { RK_Declaration = 0, //< Refers to a declaration - RK_Keyword //< Refers to a keyword or symbol. + RK_Keyword, //< Refers to a keyword or symbol. + RK_Macro //< Refers to a macro }; /// \brief The kind of result stored here. @@ -164,6 +166,9 @@ public: /// \brief When Kind == RK_Keyword, the string representing the keyword /// or symbol's spelling. const char *Keyword; + + /// \brief When Kind == RK_Macro, the identifier that refers to a macro. + IdentifierInfo *Macro; }; /// \brief Describes how good this result is, with zero being the best @@ -199,6 +204,12 @@ public: QualifierIsInformative(0), StartsNestedNameSpecifier(false), Qualifier(0) { } + /// \brief Build a result that refers to a macro. + Result(IdentifierInfo *Macro, unsigned Rank) + : Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false), + QualifierIsInformative(0), StartsNestedNameSpecifier(false), + Qualifier(0) { } + /// \brief Retrieve the declaration stored in this result. NamedDecl *getDeclaration() const { assert(Kind == RK_Declaration && "Not a declaration result"); |