diff options
Diffstat (limited to 'include')
54 files changed, 1182 insertions, 428 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 84ec472..7bc290d 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -18,6 +18,7 @@ #include <sys/stat.h> #include <time.h> +#include <stdio.h> #ifdef __cplusplus extern "C" { @@ -86,14 +87,12 @@ struct CXUnsavedFile { const char *Filename; /** - * \brief A null-terminated buffer containing the unsaved contents - * of this file. + * \brief A buffer containing the unsaved contents of this file. */ const char *Contents; /** - * \brief The length of the unsaved contents of this buffer, not - * counting the NULL at the end of the buffer. + * \brief The length of the unsaved contents of this buffer. */ unsigned long Length; }; @@ -145,8 +144,8 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); * * Here is an example: * - * // excludeDeclsFromPCH = 1 - * Idx = clang_createIndex(1); + * // excludeDeclsFromPCH = 1, displayDiagnostics=1 + * Idx = clang_createIndex(1, 1); * * // IndexTest.pch was produced with the following command: * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" @@ -170,7 +169,8 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks * (which gives the indexer the same performance benefit as the compiler). */ -CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH); +CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics); /** * \brief Destroy the given index. @@ -207,7 +207,7 @@ typedef void *CXFile; /** * \brief Retrieve the complete file and path name of the given file. */ -CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile); +CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile); /** * \brief Retrieve the last modification time of the given file. @@ -388,45 +388,105 @@ enum CXDiagnosticSeverity { }; /** - * \brief Describes the kind of fix-it hint expressed within a - * diagnostic. + * \brief A single diagnostic, containing the diagnostic's severity, + * location, text, source ranges, and fix-it hints. */ -enum CXFixItKind { +typedef void *CXDiagnostic; + +/** + * \brief Determine the number of diagnostics produced for the given + * translation unit. + */ +CINDEX_LINKAGE unsigned clang_getNumDiagnostics(CXTranslationUnit Unit); + +/** + * \brief Retrieve a diagnostic associated with the given translation unit. + * + * \param Unit the translation unit to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, + unsigned Index); + +/** + * \brief Destroy a diagnostic. + */ +CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); + +/** + * \brief Options to control the display of diagnostics. + * + * The values in this enum are meant to be combined to customize the + * behavior of \c clang_displayDiagnostic(). + */ +enum CXDiagnosticDisplayOptions { /** - * \brief A fix-it hint that inserts code at a particular position. + * \brief Display the source-location information where the + * diagnostic was located. + * + * When set, diagnostics will be prefixed by the file, line, and + * (optionally) column to which the diagnostic refers. For example, + * + * \code + * test.c:28: warning: extra tokens at end of #endif directive + * \endcode + * + * This option corresponds to the clang flag \c -fshow-source-location. */ - CXFixIt_Insertion = 0, + CXDiagnostic_DisplaySourceLocation = 0x01, /** - * \brief A fix-it hint that removes code within a range. + * \brief If displaying the source-location information of the + * diagnostic, also include the column number. + * + * This option corresponds to the clang flag \c -fshow-column. */ - CXFixIt_Removal = 1, + CXDiagnostic_DisplayColumn = 0x02, /** - * \brief A fix-it hint that replaces the code within a range with another - * string. + * \brief If displaying the source-location information of the + * diagnostic, also include information about source ranges in a + * machine-parsable format. + * + * This option corresponds to the clang flag + * \c -fdiagnostics-print-source-range-info. */ - CXFixIt_Replacement = 2 + CXDiagnostic_DisplaySourceRanges = 0x04 }; /** - * \brief A single diagnostic, containing the diagnostic's severity, - * location, text, source ranges, and fix-it hints. + * \brief Format the given diagnostic in a manner that is suitable for display. + * + * This routine will format the given diagnostic to a string, rendering + * the diagnostic according to the various options given. The + * \c clang_defaultDiagnosticDisplayOptions() function returns the set of + * options that most closely mimics the behavior of the clang compiler. + * + * \param Diagnostic The diagnostic to print. + * + * \param Options A set of options that control the diagnostic display, + * created by combining \c CXDiagnosticDisplayOptions values. + * + * \returns A new string containing for formatted diagnostic. */ -typedef void *CXDiagnostic; +CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, + unsigned Options); /** - * \brief Callback function invoked for each diagnostic emitted during - * translation. - * - * \param Diagnostic the diagnostic emitted during translation. This - * diagnostic pointer is only valid during the execution of the - * callback. + * \brief Retrieve the set of display options most similar to the + * default behavior of the clang compiler. * - * \param ClientData the callback client data. + * \returns A set of display options suitable for use with \c + * clang_displayDiagnostic(). + */ +CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); + +/** + * \brief Print a diagnostic to the given file. */ -typedef void (*CXDiagnosticCallback)(CXDiagnostic Diagnostic, - CXClientData ClientData); /** * \brief Determine the severity of the given diagnostic. @@ -476,69 +536,33 @@ CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); /** - * \brief Retrieve the kind of the given fix-it. - * - * \param Diagnostic the diagnostic whose fix-its are being queried. - * - * \param FixIt the zero-based index of the fix-it to query. - */ -CINDEX_LINKAGE enum CXFixItKind -clang_getDiagnosticFixItKind(CXDiagnostic Diagnostic, unsigned FixIt); - -/** - * \brief Retrieve the insertion information for an insertion fix-it. + * \brief Retrieve the replacement information for a given fix-it. * - * For a fix-it that describes an insertion into a text buffer, - * retrieve the source location where the text should be inserted and - * the text to be inserted. + * Fix-its are described in terms of a source range whose contents + * should be replaced by a string. This approach generalizes over + * three kinds of operations: removal of source code (the range covers + * the code to be removed and the replacement string is empty), + * replacement of source code (the range covers the code to be + * replaced and the replacement string provides the new code), and + * insertion (both the start and end of the range point at the + * insertion location, and the replacement string provides the text to + * insert). * - * \param Diagnostic the diagnostic whose fix-its are being queried. + * \param Diagnostic The diagnostic whose fix-its are being queried. * - * \param FixIt the zero-based index of the insertion fix-it. + * \param FixIt The zero-based index of the fix-it. * - * \param Location will be set to the location where text should be - * inserted. + * \param ReplacementRange The source range whose contents will be + * replaced with the returned replacement string. Note that source + * ranges are half-open ranges [a, b), so the source code should be + * replaced from a and up to (but not including) b. * - * \returns the text string to insert at the given location. + * \returns A string containing text that should be replace the source + * code indicated by the \c ReplacementRange. */ -CINDEX_LINKAGE CXString -clang_getDiagnosticFixItInsertion(CXDiagnostic Diagnostic, unsigned FixIt, - CXSourceLocation *Location); - -/** - * \brief Retrieve the removal information for a removal fix-it. - * - * For a fix-it that describes a removal from a text buffer, retrieve - * the source range that should be removed. - * - * \param Diagnostic the diagnostic whose fix-its are being queried. - * - * \param FixIt the zero-based index of the removal fix-it. - * - * \returns a source range describing the text that should be removed - * from the buffer. - */ -CINDEX_LINKAGE CXSourceRange -clang_getDiagnosticFixItRemoval(CXDiagnostic Diagnostic, unsigned FixIt); - -/** - * \brief Retrieve the replacement information for an replacement fix-it. - * - * For a fix-it that describes replacement of text in the text buffer - * with alternative text. - * - * \param Diagnostic the diagnostic whose fix-its are being queried. - * - * \param FixIt the zero-based index of the replacement fix-it. - * - * \param Range will be set to the source range whose text should be - * replaced with the returned text. - * - * \returns the text string to use as replacement text. - */ -CINDEX_LINKAGE CXString -clang_getDiagnosticFixItReplacement(CXDiagnostic Diagnostic, unsigned FixIt, - CXSourceRange *Range); +CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, + unsigned FixIt, + CXSourceRange *ReplacementRange); /** * @} @@ -600,17 +624,13 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( int num_clang_command_line_args, const char **clang_command_line_args, unsigned num_unsaved_files, - struct CXUnsavedFile *unsaved_files, - CXDiagnosticCallback diag_callback, - CXClientData diag_client_data); + struct CXUnsavedFile *unsaved_files); /** * \brief Create a translation unit from an AST file (-emit-ast). */ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, - const char *ast_filename, - CXDiagnosticCallback diag_callback, - CXClientData diag_client_data); + const char *ast_filename); /** * \brief Destroy the specified CXTranslationUnit object. @@ -764,7 +784,19 @@ enum CXCursorKind { * The translation unit cursor exists primarily to act as the root * cursor for traversing the contents of a translation unit. */ - CXCursor_TranslationUnit = 300 + CXCursor_TranslationUnit = 300, + + /* Attributes */ + CXCursor_FirstAttr = 400, + /** + * \brief An attribute whose specific kind is not exposed via this + * interface. + */ + CXCursor_UnexposedAttr = 400, + + CXCursor_IBActionAttr = 401, + CXCursor_IBOutletAttr = 402, + CXCursor_LastAttr = CXCursor_IBOutletAttr }; /** @@ -857,6 +889,32 @@ CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind); /** + * \brief Describe the linkage of the entity referred to by a cursor. + */ +enum CXLinkageKind { + /** \brief This value indicates that no linkage information is available + * for a provided CXCursor. */ + CXLinkage_Invalid, + /** + * \brief This is the linkage for variables, parameters, and so on that + * have automatic storage. This covers normal (non-extern) local variables. + */ + CXLinkage_NoLinkage, + /** \brief This is the linkage for static variables and static functions. */ + CXLinkage_Internal, + /** \brief This is the linkage for entities with external linkage that live + * in C++ anonymous namespaces.*/ + CXLinkage_UniqueExternal, + /** \brief This is the linkage for entities with true, external linkage. */ + CXLinkage_External +}; + +/** + * \brief Determine the linkage of the entity referred to be a given cursor. + */ +CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor); + +/** * @} */ @@ -1221,7 +1279,7 @@ CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, */ /* for debug/testing */ -CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); +CINDEX_LINKAGE CXString clang_getCursorKindSpelling(enum CXCursorKind Kind); CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, const char **startBuf, const char **endBuf, @@ -1229,7 +1287,7 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, unsigned *startColumn, unsigned *endLine, unsigned *endColumn); - +CINDEX_LINKAGE void clang_enableStackTraces(void); /** * @} */ @@ -1313,13 +1371,13 @@ enum CXCompletionChunkKind { * - a Placeholder chunk for "int x" * - an Optional chunk containing the remaining defaulted arguments, e.g., * - a Comma chunk for "," - * - a Placeholder chunk for "float x" + * - a Placeholder chunk for "float y" * - an Optional chunk containing the last defaulted argument: * - a Comma chunk for "," * - a Placeholder chunk for "double z" * - a RightParen chunk for ")" * - * There are many ways two handle Optional chunks. Two simple approaches are: + * There are many ways to handle Optional chunks. Two simple approaches are: * - Completely ignore optional chunks, in which case the template for the * function "f" would only include the first parameter ("int x"). * - Fully expand all optional chunks, in which case the template for the @@ -1478,7 +1536,7 @@ clang_getCompletionChunkKind(CXCompletionString completion_string, * * \returns the text associated with the chunk at index \c chunk_number. */ -CINDEX_LINKAGE const char * +CINDEX_LINKAGE CXString clang_getCompletionChunkText(CXCompletionString completion_string, unsigned chunk_number); @@ -1613,9 +1671,7 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, struct CXUnsavedFile *unsaved_files, const char *complete_filename, unsigned complete_line, - unsigned complete_column, - CXDiagnosticCallback diag_callback, - CXClientData diag_client_data); + unsigned complete_column); /** * \brief Free the given set of code-completion results. @@ -1624,6 +1680,26 @@ CINDEX_LINKAGE void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); /** + * \brief Determine the number of diagnostics produced prior to the + * location where code completion was performed. + */ +CINDEX_LINKAGE +unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results); + +/** + * \brief Retrieve a diagnostic associated with the given code completion. + * + * \param Result the code completion results to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE +CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, + unsigned Index); + +/** * @} */ diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2ed9fd7..6767f52 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -67,6 +67,28 @@ namespace clang { namespace Builtin { class Context; } +/// \brief A vector of C++ member functions that is optimized for +/// storing a single method. +class CXXMethodVector { + /// \brief Storage for the vector. + /// + /// When the low bit is zero, this is a const CXXMethodDecl *. When the + /// low bit is one, this is a std::vector<const CXXMethodDecl *> *. + mutable uintptr_t Storage; + + typedef std::vector<const CXXMethodDecl *> vector_type; + +public: + CXXMethodVector() : Storage(0) { } + + typedef const CXXMethodDecl **iterator; + iterator begin() const; + iterator end() const; + + void push_back(const CXXMethodDecl *Method); + void Destroy(); +}; + /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. class ASTContext { @@ -219,6 +241,14 @@ class ASTContext { llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; + /// \brief Mapping that stores the methods overridden by a given C++ + /// member function. + /// + /// Since most C++ member functions aren't virtual and therefore + /// don't override anything, we store the overridden functions in + /// this map on the side rather than within the CXXMethodDecl structure. + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; + TranslationUnitDecl *TUDecl; /// SourceMgr - The associated SourceManager object. @@ -310,6 +340,19 @@ public: void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + // Access to the set of methods overridden by the given C++ method. + typedef CXXMethodVector::iterator overridden_cxx_method_iterator; + overridden_cxx_method_iterator + overridden_methods_begin(const CXXMethodDecl *Method) const; + + overridden_cxx_method_iterator + overridden_methods_end(const CXXMethodDecl *Method) const; + + /// \brief Note that the given C++ \p Method overrides the given \p + /// Overridden method. + void addOverriddenMethod(const CXXMethodDecl *Method, + const CXXMethodDecl *Overridden); + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } @@ -529,11 +572,11 @@ public: /// list. isVariadic indicates whether the argument list includes '...'. QualType getFunctionType(QualType ResultTy, const QualType *ArgArray, unsigned NumArgs, bool isVariadic, - unsigned TypeQuals, bool hasExceptionSpec = false, - bool hasAnyExceptionSpec = false, - unsigned NumExs = 0, const QualType *ExArray = 0, - bool NoReturn = false, - CallingConv CallConv = CC_Default); + unsigned TypeQuals, bool hasExceptionSpec, + bool hasAnyExceptionSpec, + unsigned NumExs, const QualType *ExArray, + bool NoReturn, + CallingConv CallConv); /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. @@ -882,9 +925,8 @@ public: llvm::SmallVectorImpl<FieldDecl*> &Fields); void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars, - bool CollectSynthesized = true); - void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + void CollectNonClassIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index f5f11ca..7975c43 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -156,6 +156,12 @@ namespace clang { /// \returns the equivalent identifier in the "to" context. IdentifierInfo *Import(IdentifierInfo *FromId); + /// \brief Import the given Objective-C selector from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent selector in the "to" context. + Selector Import(Selector FromSel); + /// \brief Import the given file ID from the "from" context into the /// "to" context. /// diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 3722590..1974493 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -62,7 +62,8 @@ public: FormatArg, GNUInline, Hiding, - IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with + IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. + IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. Malloc, NoDebug, NoInline, @@ -72,8 +73,10 @@ public: ObjCException, ObjCNSObject, Override, - CFReturnsRetained, // Clang/Checker-specific. - NSReturnsRetained, // Clang/Checker-specific. + CFReturnsRetained, // Clang/Checker-specific. + CFReturnsNotRetained, // Clang/Checker-specific. + NSReturnsRetained, // Clang/Checker-specific. + NSReturnsNotRetained, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, PragmaPack, @@ -91,6 +94,7 @@ public: WarnUnusedResult, Weak, WeakImport, + WeakRef, FIRST_TARGET_ATTRIBUTE, DLLExport, @@ -300,37 +304,38 @@ public: static bool classof(const DestructorAttr *A) { return true; } }; -class GNUInlineAttr : public Attr { +class IBOutletAttr : public Attr { public: - GNUInlineAttr() : Attr(GNUInline) {} + IBOutletAttr() : Attr(IBOutletKind) {} virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == GNUInline; + return A->getKind() == IBOutletKind; } - static bool classof(const GNUInlineAttr *A) { return true; } + static bool classof(const IBOutletAttr *A) { return true; } }; -class IBOutletAttr : public Attr { +class IBActionAttr : public Attr { public: - IBOutletAttr() : Attr(IBOutletKind) {} + IBActionAttr() : Attr(IBActionKind) {} virtual Attr *clone(ASTContext &C) const; - // Implement isa/cast/dyncast/etc. + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == IBOutletKind; + return A->getKind() == IBActionKind; } - static bool classof(const IBOutletAttr *A) { return true; } + static bool classof(const IBActionAttr *A) { return true; } }; -DEF_SIMPLE_ATTR(Malloc); -DEF_SIMPLE_ATTR(NoReturn); DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); DEF_SIMPLE_ATTR(Final); +DEF_SIMPLE_ATTR(GNUInline); +DEF_SIMPLE_ATTR(Malloc); +DEF_SIMPLE_ATTR(NoReturn); class SectionAttr : public AttrWithString { public: @@ -353,6 +358,7 @@ DEF_SIMPLE_ATTR(Unused); DEF_SIMPLE_ATTR(Used); DEF_SIMPLE_ATTR(Weak); DEF_SIMPLE_ATTR(WeakImport); +DEF_SIMPLE_ATTR(WeakRef); DEF_SIMPLE_ATTR(NoThrow); DEF_SIMPLE_ATTR(Const); DEF_SIMPLE_ATTR(Pure); @@ -543,7 +549,9 @@ public: }; // Checker-specific attributes. +DEF_SIMPLE_ATTR(CFReturnsNotRetained); DEF_SIMPLE_ATTR(CFReturnsRetained); +DEF_SIMPLE_ATTR(NSReturnsNotRetained); DEF_SIMPLE_ATTR(NSReturnsRetained); // C++0x member checking attributes. diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 79a3022..c89e5e4 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -16,6 +16,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" #include "llvm/ADT/SmallVector.h" @@ -159,7 +160,11 @@ class CXXBasePaths { friend class CXXRecordDecl; void ComputeDeclsFound(); - + + bool lookupInBases(ASTContext &Context, + const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback *BaseMatches, + void *UserData); public: typedef std::list<CXXBasePath>::iterator paths_iterator; typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 93e41d3..1f459b0 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -120,6 +120,13 @@ public: return Stored.isLocalRestrictQualified(); } + /// \brief Determines if this canonical type is furthermore + /// canonical as a parameter. The parameter-canonicalization + /// process decays arrays to pointers and drops top-level qualifiers. + bool isCanonicalAsParam() const { + return Stored.isCanonicalAsParam(); + } + /// \brief Retrieve the unqualified form of this type. CanQual<T> getUnqualifiedType() const; @@ -157,6 +164,10 @@ public: /// ensure that the given type is a canonical type with the correct // (dynamic) type. static CanQual<T> CreateUnsafe(QualType Other); + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(getAsOpaquePtr()); + } }; template<typename T, typename U> @@ -172,6 +183,10 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) { /// \brief Represents a canonical, potentially-qualified type. typedef CanQual<Type> CanQualType; +inline CanQualType Type::getCanonicalTypeUnqualified() const { + return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); +} + inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, CanQualType T) { DB << static_cast<QualType>(T); @@ -547,18 +562,24 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { template<> struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) }; template<> struct CanProxyAdaptor<FunctionNoProtoType> : public CanProxyBase<FunctionNoProtoType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) }; template<> struct CanProxyAdaptor<FunctionProtoType> : public CanProxyBase<FunctionProtoType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs) CanQualType getArgType(unsigned i) const { return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0744289..91aeff3 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -267,8 +267,8 @@ public: } void setAnonymousNamespace(NamespaceDecl *D) { - assert(D->isAnonymousNamespace()); - assert(D->getParent() == this); + assert(!D || D->isAnonymousNamespace()); + assert(!D || D->getParent() == this); AnonymousNamespace = D; } @@ -561,7 +561,7 @@ public: /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. - bool isOutOfLine() const; + virtual bool isOutOfLine() const; /// \brief If this is a static data member, find its out-of-line definition. VarDecl *getOutOfLineDefinition(); @@ -1306,7 +1306,7 @@ public: /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. - bool isOutOfLine() const; + virtual bool isOutOfLine() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index a407a16..7fb5f9d 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -279,7 +279,8 @@ public: /// \brief Whether this declaration was used, meaning that a definition /// is required. - bool isUsed() const { return Used; } + bool isUsed() const; + void setUsed(bool U = true) { Used = U; } /// \brief Retrieve the level of precompiled header from which this @@ -330,7 +331,7 @@ public: return const_cast<Decl*>(this)->getLexicalDeclContext(); } - bool isOutOfLine() const { + virtual bool isOutOfLine() const { return getLexicalDeclContext() != getDeclContext(); } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 0978c6d..af00c8d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -710,7 +710,7 @@ public: CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); /// getDestructor - Returns the destructor decl for this class. - CXXDestructorDecl *getDestructor(ASTContext &Context); + CXXDestructorDecl *getDestructor(ASTContext &Context) const; /// isLocalClass - If the class is a local class [class.local], returns /// the enclosing function declaration. @@ -751,6 +751,21 @@ public: /// tangling input and output in \p Paths bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; + /// \brief Determine whether this class is virtually derived from + /// the class \p Base. + /// + /// This routine only determines whether this class is virtually + /// derived from \p Base, but does not account for factors that may + /// make a Derived -> Base class ill-formed, such as + /// private/protected inheritance or multiple, ambiguous base class + /// subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \returns true if this class is virtually derived from Base, + /// false otherwise. + bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const; + /// \brief Determine whether this class is provably not derived from /// the type \p Base. bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const; @@ -824,6 +839,18 @@ public: /// base class that we are searching for. static bool FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BaseRecord); + + /// \brief Base-class lookup callback that determines whether the + /// given base class specifier refers to a specific class + /// declaration and describes virtual derivation. + /// + /// This callback can be used with \c lookupInBases() to determine + /// whether a given derived class has is a virtual base class + /// subobject of a particular type. The user data pointer should + /// refer to the canonical CXXRecordDecl of the base class that we + /// are searching for. + static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *BaseRecord); /// \brief Base-class lookup callback that determines whether there exists /// a tag with the given name. diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e562d35..26656bf 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -494,11 +494,13 @@ public: } unsigned protocol_size() const { return ReferencedProtocols.size(); } - typedef ObjCList<ObjCIvarDecl>::iterator ivar_iterator; - ivar_iterator ivar_begin() const { return IVars.begin(); } - ivar_iterator ivar_end() const { return IVars.end(); } - unsigned ivar_size() const { return IVars.size(); } - bool ivar_empty() const { return IVars.empty(); } + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } + ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); + } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } /// setProtocolList - Set the list of protocols that this interface /// implements. @@ -514,10 +516,6 @@ public: const SourceLocation *Locs, ASTContext &C); - void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) { - IVars.set(List, Num, C); - } - bool isForwardDecl() const { return ForwardDecl; } void setForwardDecl(bool val) { ForwardDecl = val; } @@ -529,6 +527,8 @@ public: CategoryList = category; } + ObjCCategoryDecl* getClassExtension() const; + /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. bool isSuperClassOf(const ObjCInterfaceDecl *I) const { @@ -951,6 +951,20 @@ public: bool IsClassExtension() const { return getIdentifier() == 0; } + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { + return ivar_iterator(decls_begin()); + } + ivar_iterator ivar_end() const { + return ivar_iterator(decls_end()); + } + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); + } + bool ivar_empty() const { + return ivar_begin() == ivar_end(); + } + SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation At) { AtLoc = At; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 114a198..23076b9 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -150,7 +150,8 @@ public: LV_InvalidExpression, LV_MemberFunction, LV_SubObjCPropertySetting, - LV_SubObjCPropertyGetterSetting + LV_SubObjCPropertyGetterSetting, + LV_ClassTemporary }; isLvalueResult isLvalue(ASTContext &Ctx) const; @@ -181,7 +182,8 @@ public: MLV_NoSetterProperty, MLV_MemberFunction, MLV_SubObjCPropertySetting, - MLV_SubObjCPropertyGetterSetting + MLV_SubObjCPropertyGetterSetting, + MLV_ClassTemporary }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index e4bc4b7..d1351b8 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -997,21 +997,59 @@ public: virtual child_iterator child_end(); }; +/// \brief Structure used to store the type being destroyed by a +/// pseudo-destructor expression. +class PseudoDestructorTypeStorage { + /// \brief Either the type source information or the name of the type, if + /// it couldn't be resolved due to type-dependence. + llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; + + /// \brief The starting source location of the pseudo-destructor type. + SourceLocation Location; + +public: + PseudoDestructorTypeStorage() { } + + PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) + : Type(II), Location(Loc) { } + + PseudoDestructorTypeStorage(TypeSourceInfo *Info); + + TypeSourceInfo *getTypeSourceInfo() const { + return Type.dyn_cast<TypeSourceInfo *>(); + } + + IdentifierInfo *getIdentifier() const { + return Type.dyn_cast<IdentifierInfo *>(); + } + + SourceLocation getLocation() const { return Location; } +}; + /// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). /// -/// Example: +/// A pseudo-destructor is an expression that looks like a member access to a +/// destructor of a scalar type, except that scalar types don't have +/// destructors. For example: /// /// \code +/// typedef int T; +/// void f(int *p) { +/// p->T::~T(); +/// } +/// \endcode +/// +/// Pseudo-destructors typically occur when instantiating templates such as: +/// +/// \code /// template<typename T> /// void destroy(T* ptr) { -/// ptr->~T(); +/// ptr->T::~T(); /// } /// \endcode /// -/// When the template is parsed, the expression \c ptr->~T will be stored as -/// a member reference expression. If it then instantiated with a scalar type -/// as a template argument for T, the resulting expression will be a -/// pseudo-destructor expression. +/// for scalar types. A pseudo-destructor expression has no run-time semantics +/// beyond evaluating the base expression. class CXXPseudoDestructorExpr : public Expr { /// \brief The base expression (that is being destroyed). Stmt *Base; @@ -1030,28 +1068,44 @@ class CXXPseudoDestructorExpr : public Expr { /// present. SourceRange QualifierRange; - /// \brief The type being destroyed. - QualType DestroyedType; - - /// \brief The location of the type after the '~'. - SourceLocation DestroyedTypeLoc; + /// \brief The type that precedes the '::' in a qualified pseudo-destructor + /// expression. + TypeSourceInfo *ScopeType; + + /// \brief The location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation ColonColonLoc; + + /// \brief The location of the '~'. + SourceLocation TildeLoc; + + /// \brief The type being destroyed, or its name if we were unable to + /// resolve the name. + PseudoDestructorTypeStorage DestroyedType; public: CXXPseudoDestructorExpr(ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - QualType DestroyedType, - SourceLocation DestroyedTypeLoc) + TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, - false, 0)), - /*isTypeDependent=*/false, + false, 0, false, + false, 0, 0, false, + CC_Default)), + /*isTypeDependent=*/(Base->isTypeDependent() || + (DestroyedType.getTypeSourceInfo() && + DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), /*isValueDependent=*/Base->isValueDependent()), Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), DestroyedType(DestroyedType), - DestroyedTypeLoc(DestroyedTypeLoc) { } + QualifierRange(QualifierRange), + ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), + DestroyedType(DestroyedType) { } void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } @@ -1079,15 +1133,51 @@ public: /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieve the type that is being destroyed. - QualType getDestroyedType() const { return DestroyedType; } - - /// \brief Retrieve the location of the type being destroyed. - SourceLocation getDestroyedTypeLoc() const { return DestroyedTypeLoc; } - - virtual SourceRange getSourceRange() const { - return SourceRange(Base->getLocStart(), DestroyedTypeLoc); + /// \brief Retrieve the scope type in a qualified pseudo-destructor + /// expression. + /// + /// Pseudo-destructor expressions can have extra qualification within them + /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). + /// Here, if the object type of the expression is (or may be) a scalar type, + /// \p T may also be a scalar type and, therefore, cannot be part of a + /// nested-name-specifier. It is stored as the "scope type" of the pseudo- + /// destructor expression. + TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } + + /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation getColonColonLoc() const { return ColonColonLoc; } + + /// \brief Retrieve the location of the '~'. + SourceLocation getTildeLoc() const { return TildeLoc; } + + /// \brief Retrieve the source location information for the type + /// being destroyed. + /// + /// This type-source information is available for non-dependent + /// pseudo-destructor expressions and some dependent pseudo-destructor + /// expressions. Returns NULL if we only have the identifier for a + /// dependent pseudo-destructor expression. + TypeSourceInfo *getDestroyedTypeInfo() const { + return DestroyedType.getTypeSourceInfo(); } + + /// \brief In a dependent pseudo-destructor expression for which we do not + /// have full type information on the destroyed type, provides the name + /// of the destroyed type. + IdentifierInfo *getDestroyedTypeIdentifier() const { + return DestroyedType.getIdentifier(); + } + + /// \brief Retrieve the type being destroyed. + QualType getDestroyedType() const; + + /// \brief Retrieve the starting location of the type being destroyed. + SourceLocation getDestroyedTypeLoc() const { + return DestroyedType.getLocation(); + } + + virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 40e5098..bd8a6bc 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -90,9 +90,13 @@ namespace clang { class TemplateArgument; class TemplateArgumentLoc; class TemplateArgumentListInfo; + class Type; class QualifiedNameType; struct PrintingPolicy; + template <typename> class CanQual; + typedef CanQual<Type> CanQualType; + // Provide forward declarations for all of the *Type classes #define TYPE(Class, Base) class Class##Type; #include "clang/AST/TypeNodes.def" @@ -976,7 +980,10 @@ public: /// \brief Determine the linkage of this type. virtual Linkage getLinkage() const; - QualType getCanonicalTypeInternal() const { return CanonicalType; } + QualType getCanonicalTypeInternal() const { + return CanonicalType; + } + CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; static bool classof(const Type *) { return true; } }; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 9cf2cb7..8187cad 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -31,7 +31,11 @@ // type that is always dependent. Clients that do not need to deal // with uninstantiated C++ templates can ignore these types. // -// There is a fifth macro, independent of the others. Most clients +// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that +// is non-canonical unless it is dependent. Defaults to TYPE because +// it is neither reliably dependent nor reliably non-canonical. +// +// There is a sixth macro, independent of the others. Most clients // will not need to use it. // // LEAF_TYPE(Class) - A type that never has inner types. Clients @@ -51,6 +55,10 @@ # define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) #endif +#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE +# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) +#endif + TYPE(Builtin, Type) TYPE(Complex, Type) TYPE(Pointer, Type) @@ -72,16 +80,16 @@ TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Typedef, Type) -NON_CANONICAL_TYPE(TypeOfExpr, Type) -NON_CANONICAL_TYPE(TypeOf, Type) -NON_CANONICAL_TYPE(Decltype, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) ABSTRACT_TYPE(Tag, Type) TYPE(Record, TagType) TYPE(Enum, TagType) NON_CANONICAL_TYPE(Elaborated, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) -TYPE(TemplateSpecialization, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) @@ -101,6 +109,7 @@ LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE #endif +#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE #undef DEPENDENT_TYPE #undef NON_CANONICAL_TYPE #undef ABSTRACT_TYPE diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h index a4ad0b7..e4f7c57 100644 --- a/include/clang/Analysis/Analyses/PrintfFormatString.h +++ b/include/clang/Analysis/Analyses/PrintfFormatString.h @@ -75,11 +75,14 @@ public: VoidPtrArg, // 'p' OutIntPtrArg, // 'n' PercentArg, // '%' - // Objective-C specific specifiers. + // MacOS X unicode extensions. + CArg, // 'C' + UnicodeStrArg, // 'S' + // Objective-C specific specifiers. ObjCObjArg, // '@' - // GlibC specific specifiers. + // GlibC specific specifiers. PrintErrno, // 'm' - // Specifier ranges. + // Specifier ranges. IntArgBeg = dArg, IntArgEnd = iArg, UIntArgBeg = oArg, @@ -147,20 +150,27 @@ enum LengthModifier { class OptionalAmount { public: - enum HowSpecified { NotSpecified, Constant, Arg }; + enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; - OptionalAmount(HowSpecified h, const char *st) - : start(st), hs(h), amt(0) {} + OptionalAmount(HowSpecified h, unsigned i, const char *st) + : start(st), hs(h), amt(i) {} - OptionalAmount() - : start(0), hs(NotSpecified), amt(0) {} + OptionalAmount(bool b = true) + : start(0), hs(b ? NotSpecified : Invalid), amt(0) {} - OptionalAmount(unsigned i, const char *st) - : start(st), hs(Constant), amt(i) {} + bool isInvalid() const { + return hs == Invalid; + } HowSpecified getHowSpecified() const { return hs; } + bool hasDataArgument() const { return hs == Arg; } + unsigned getArgIndex() const { + assert(hasDataArgument()); + return amt; + } + unsigned getConstantAmount() const { assert(hs == Constant); return amt; @@ -185,14 +195,19 @@ class FormatSpecifier { unsigned HasSpacePrefix : 1; unsigned HasAlternativeForm : 1; unsigned HasLeadingZeroes : 1; - unsigned flags : 5; + /// Positional arguments, an IEEE extension: + /// IEEE Std 1003.1, 2004 Edition + /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html + unsigned UsesPositionalArg : 1; + unsigned argIndex; ConversionSpecifier CS; OptionalAmount FieldWidth; OptionalAmount Precision; public: FormatSpecifier() : LM(None), IsLeftJustified(0), HasPlusPrefix(0), HasSpacePrefix(0), - HasAlternativeForm(0), HasLeadingZeroes(0) {} + HasAlternativeForm(0), HasLeadingZeroes(0), UsesPositionalArg(0), + argIndex(0) {} static FormatSpecifier Parse(const char *beg, const char *end); @@ -208,6 +223,17 @@ public: void setHasSpacePrefix() { HasSpacePrefix = 1; } void setHasAlternativeForm() { HasAlternativeForm = 1; } void setHasLeadingZeros() { HasLeadingZeroes = 1; } + void setUsesPositionalArg() { UsesPositionalArg = 1; } + + void setArgIndex(unsigned i) { + assert(CS.consumesDataArgument()); + argIndex = i; + } + + unsigned getArgIndex() const { + assert(CS.consumesDataArgument()); + return argIndex; + } // Methods for querying the format specifier. @@ -247,8 +273,11 @@ public: bool hasAlternativeForm() const { return (bool) HasAlternativeForm; } bool hasLeadingZeros() const { return (bool) HasLeadingZeroes; } bool hasSpacePrefix() const { return (bool) HasSpacePrefix; } + bool usesPositionalArg() const { return (bool) UsesPositionalArg; } }; +enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; + class FormatStringHandler { public: FormatStringHandler() {} @@ -259,10 +288,15 @@ public: virtual void HandleNullChar(const char *nullCharacter) {} - virtual void + virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, + PositionContext p) {} + + virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} + + virtual bool HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, const char *startSpecifier, - unsigned specifierLen) {} + unsigned specifierLen) { return true; } virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, const char *startSpecifier, diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h new file mode 100644 index 0000000..e0c84f9 --- /dev/null +++ b/include/clang/Analysis/Analyses/ReachableCode.h @@ -0,0 +1,55 @@ +//===- ReachableCode.h -----------------------------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A flow-sensitive, path-insensitive analysis of unreachable code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REACHABLECODE_H +#define LLVM_CLANG_REACHABLECODE_H + +#include "clang/Basic/SourceLocation.h" + +//===----------------------------------------------------------------------===// +// Forward declarations. +//===----------------------------------------------------------------------===// + +namespace llvm { + class BitVector; +} + +namespace clang { + class AnalysisContext; + class CFGBlock; +} + +//===----------------------------------------------------------------------===// +// API. +//===----------------------------------------------------------------------===// + +namespace clang { +namespace reachable_code { + +class Callback { +public: + virtual ~Callback() {} + virtual void HandleUnreachable(SourceLocation L, SourceRange R1, + SourceRange R2) = 0; +}; + +/// ScanReachableFromBlock - Mark all blocks reachable from Start. +/// Returns the total number of blocks that were marked reachable. +unsigned ScanReachableFromBlock(const CFGBlock &Start, + llvm::BitVector &Reachable); + +void FindUnreachableCode(AnalysisContext &AC, Callback &CB); + +}} // end namespace clang::reachable_code + +#endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index ea4f5b2..bde4417 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -110,6 +110,8 @@ public: const LocationContext *getParent() const { return Parent; } + bool isParentOf(const LocationContext *LC) const; + const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } CFG *getCFG() const { return getAnalysisContext()->getCFG(); } diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index e87784f..528cf87 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -245,8 +245,6 @@ public: Stmt* getLabel() { return Label; } const Stmt* getLabel() const { return Label; } - void reverseStmts(); - unsigned getBlockID() const { return BlockID; } void dump(const CFG *cfg, const LangOptions &LO) const; diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 332f9d3..fb8d4d5 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -26,6 +26,7 @@ namespace clang { class LocationContext; +class FunctionDecl; class ProgramPoint { public: @@ -41,6 +42,8 @@ public: PostPurgeDeadSymbolsKind, PostStmtCustomKind, PostLValueKind, + CallEnterKind, + CallExitKind, MinPostStmtKind = PostStmtKind, MaxPostStmtKind = PostLValueKind }; @@ -308,6 +311,36 @@ public: } }; +class CallEnter : public StmtPoint { +public: + // CallEnter uses the caller's location context. + CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L) + : StmtPoint(S, fd, CallEnterKind, L, 0) {} + + const Stmt *getCallExpr() const { + return static_cast<const Stmt *>(getData1()); + } + + const FunctionDecl *getCallee() const { + return static_cast<const FunctionDecl *>(getData2()); + } + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallEnterKind; + } +}; + +class CallExit : public StmtPoint { +public: + // CallExit uses the callee's location context. + CallExit(const Stmt *S, const LocationContext *L) + : StmtPoint(S, 0, CallExitKind, L, 0) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallExitKind; + } +}; + } // end namespace clang diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 48851d0..c6c9eed 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -23,6 +23,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/ADT/PointerIntPair.h" #include <algorithm> +#include <cstring> namespace clang { diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3251ec4..9442ac3 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -317,7 +317,7 @@ BUILTIN(__builtin_frob_return_addr, "v*v*", "n") BUILTIN(__builtin_dwarf_cfa, "v*", "n") BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") -BUILTIN(__builtin_extend_pointer, "iv*", "n") +BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins BUILTIN(__builtin_object_size, "zv*i", "n") diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index d2516f8..d6c8797 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -403,13 +403,6 @@ public: /// \brief Clear out the current diagnostic. void Clear() { CurDiagID = ~0U; } - /// Deserialize - Deserialize the first diagnostic within the memory - /// [Memory, MemoryEnd), producing a new diagnostic builder describing the - /// deserialized diagnostic. If the memory does not contain a - /// diagnostic, returns a diagnostic builder with no diagnostic ID. - DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM, - const char *&Memory, const char *MemoryEnd); - private: /// getDiagnosticMappingInfo - Return the mapping info currently set for the /// specified builtin diagnostic. This returns the high bit encoding, or zero @@ -799,12 +792,54 @@ public: /// output buffer using the arguments stored in this diagnostic. void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, llvm::SmallVectorImpl<char> &OutStr) const; +}; + +/** + * \brief Represents a diagnostic in a form that can be serialized and + * deserialized. + */ +class StoredDiagnostic { + Diagnostic::Level Level; + FullSourceLoc Loc; + std::string Message; + std::vector<SourceRange> Ranges; + std::vector<CodeModificationHint> FixIts; + +public: + StoredDiagnostic(); + StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); + StoredDiagnostic(Diagnostic::Level Level, llvm::StringRef Message); + ~StoredDiagnostic(); + + /// \brief Evaluates true when this object stores a diagnostic. + operator bool() const { return Message.size() > 0; } + + Diagnostic::Level getLevel() const { return Level; } + const FullSourceLoc &getLocation() const { return Loc; } + llvm::StringRef getMessage() const { return Message; } + + typedef std::vector<SourceRange>::const_iterator range_iterator; + range_iterator range_begin() const { return Ranges.begin(); } + range_iterator range_end() const { return Ranges.end(); } + unsigned range_size() const { return Ranges.size(); } + + typedef std::vector<CodeModificationHint>::const_iterator fixit_iterator; + fixit_iterator fixit_begin() const { return FixIts.begin(); } + fixit_iterator fixit_end() const { return FixIts.end(); } + unsigned fixit_size() const { return FixIts.size(); } /// Serialize - Serialize the given diagnostic (with its diagnostic /// level) to the given stream. Serialization is a lossy operation, /// since the specific diagnostic ID and any macro-instantiation /// information is lost. - void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const; + void Serialize(llvm::raw_ostream &OS) const; + + /// Deserialize - Deserialize the first diagnostic within the memory + /// [Memory, MemoryEnd), producing a new diagnostic builder describing the + /// deserialized diagnostic. If the memory does not contain a + /// diagnostic, returns a diagnostic builder with no diagnostic ID. + static StoredDiagnostic Deserialize(FileManager &FM, SourceManager &SM, + const char *&Memory, const char *MemoryEnd); }; /// DiagnosticClient - This is an abstract interface implemented by clients of diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index b6c2b13..cc89c7c 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -53,6 +53,29 @@ def note_odr_number_of_bases : Note< "class has %0 base %plural{1:class|:classes}0">; def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; - +def err_odr_ivar_type_inconsistent : Error< + "instance variable %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def err_odr_objc_superclass_inconsistent : Error< + "class %0 has incompatible superclasses">; +def note_odr_objc_superclass : Note<"inherits from superclass %0 here">; +def note_odr_objc_missing_superclass : Note<"no corresponding superclass here">; +def err_odr_objc_method_result_type_inconsistent : Error< + "%select{class|instance}0 method %1 has incompatible result types in " + "different translation units (%2 vs. %3)">; +def err_odr_objc_method_num_params_inconsistent : Error< + "%select{class|instance}0 method %1 has a different number of parameters in " + "different translation units (%2 vs. %3)">; +def err_odr_objc_method_param_type_inconsistent : Error< + "%select{class|instance}0 method %1 has a parameter with a different types " + "in different translation units (%2 vs. %3)">; +def err_odr_objc_method_variadic_inconsistent : Error< + "%select{class|instance}0 method %1 is variadic in one translation unit " + "and not variadic in another">; +def note_odr_objc_method_here : Note< + "%select{class|instance}0 method %1 also declared here">; +def err_odr_objc_property_type_inconsistent : Error< + "property %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">; } diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index dc5ccfd..9175bef 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -88,6 +88,8 @@ def warn_ignoring_ftabstop_value : Warning< def warn_drv_missing_resource_library : Warning< "missing resource library '%0', link may fail">; def warn_drv_conflicting_deployment_targets : Warning< - "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">; + "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">; +def warn_drv_treating_input_as_cxx : Warning< + "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">; } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 79147ea..b77614b 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -82,7 +82,7 @@ def note_fixit_main_file_unchanged : Note< def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; -def err_fe_clang : Error<"error invoking%s: %s">, DefaultFatal; +def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal; // PCH reader def err_relocatable_without_without_isysroot : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 82f9eca..c3c0cf5 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -18,11 +18,13 @@ def Implicit : DiagGroup<"implicit", [ -// Empty DiagGroups: these are recognized by clang but ignored. +// Empty DiagGroups are recognized by clang but ignored. def : DiagGroup<"address">; +def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; +def BadLiteral : DiagGroup<"bad-literal">; def : DiagGroup<"c++-compat">; def : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; @@ -119,7 +121,6 @@ def VectorConversions : DiagGroup<"vector-conversions">; // clang specific def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def : DiagGroup<"write-strings">; def CharSubscript : DiagGroup<"char-subscripts">; -def ForceAlignArgPointer : DiagGroup<"force-align-arg-pointer">; // Aggregation warning settings. @@ -180,4 +181,4 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. def NonGCC : DiagGroup<"non-gcc", - [SignCompare, Conversion, ForceAlignArgPointer]>; + [SignCompare, Conversion, BadLiteral]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index bc26c3b..fb80dcc 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -146,8 +146,6 @@ def err_missing_comma_before_ellipsis : Error< def err_unexpected_typedef_ident : Error< "unexpected type name %0: expected identifier">; def err_expected_class_name : Error<"expected class name">; -def err_destructor_class_name : Error< - "expected the class name after '~' to name a destructor">; def err_unspecified_vla_size_with_static : Error< "'static' may not be used with an unspecified variable length array size">; @@ -247,8 +245,10 @@ 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' is not allowed in classes">; -def err_ident_in_pseudo_dtor_not_a_type : Error< - "identifier %0 in pseudo-destructor expression does not name a type">; +def err_destructor_tilde_identifier : Error< + "expected a class name after '~' to name a destructor">; +def err_destructor_template_id : Error< + "destructor name %0 does not refer to a template">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -300,6 +300,7 @@ def err_explicit_instantiation_with_definition : Error< "explicit template instantiation cannot have a definition; if this " "definition is meant to be an explicit specialization, add '<>' after the " "'template' keyword">; +def err_enum_template : Error<"enumeration cannot be a template">; // Constructor template diagnostics. def err_out_of_line_constructor_template_id : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 19b242e..9f77655 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -29,10 +29,12 @@ def ext_null_pointer_expr_not_ice : Extension< // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">; -def err_float_overflow : Error< - "magnitude of floating-point constant too large for type %0; maximum is %1">; -def err_float_underflow : Error< - "magnitude of floating-point constant too small for type %0; minimum is %1">; +def warn_float_overflow : Warning< + "magnitude of floating-point constant too large for type %0; maximum is %1">, + InGroup<BadLiteral>; +def warn_float_underflow : Warning< + "magnitude of floating-point constant too small for type %0; minimum is %1">, + InGroup<BadLiteral>; // C99 Designated Initializers def err_array_designator_negative : Error< @@ -253,6 +255,12 @@ def err_dup_implementation_category : Error< "reimplementation of category %1 for class %0">; def err_conflicting_ivar_type : Error< "instance variable %0 has conflicting type: %1 vs %2">; +def err_duplicate_ivar_declaration : Error< + "instance variable is already declared">; +def warn_on_superclass_use : Warning< + "class implementation may not have super class">; +def err_non_private_ivar_declaration : Error< + "only private ivars may be declared in implementation">; def err_conflicting_ivar_bitwidth : Error< "instance variable %0 has conflicting bit-field width">; def err_conflicting_ivar_name : Error< @@ -447,6 +455,8 @@ def err_qualified_member_nonclass : Error< "qualified member access refers to a member in %0">; def err_incomplete_member_access : Error< "member access into incomplete type %0">; +def err_incomplete_type : Error< + "incomplete type %0 where a complete type is required">; // C++ class members def err_storageclass_invalid_for_member : Error< @@ -486,8 +496,7 @@ def err_implicit_object_parameter_init : Error< def note_field_decl : Note<"member is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; -def note_previous_decl : Note< - "%0 declared here">; +def note_previous_decl : Note<"%0 declared here">; def note_member_synthesized_at : Note< "implicit default %select{constructor|copy constructor|" "copy assignment operator|destructor}0 for %1 first required here">; @@ -557,6 +566,10 @@ def err_destructor_typedef_name : Error< "destructor cannot be declared using a typedef %0 of the class name">; def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; +def err_destructor_class_name : Error< + "expected the class name after '~' to name a destructor">; +def err_ident_in_pseudo_dtor_not_a_type : Error< + "identifier %0 in pseudo-destructor expression does not name a type">; // C++ initialization def err_init_conversion_failed : Error< @@ -724,9 +737,6 @@ def err_attribute_aligned_not_power_of_two : Error< def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "'%0' redeclared without %1 attribute: previous %1 ignored">; def warn_attribute_ignored : Warning<"%0 attribute ignored">; -def warn_faap_attribute_ignored : Warning< - "force_align_arg_pointer used on function pointer; attribute ignored">, - InGroup<ForceAlignArgPointer>; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; def warn_attribute_void_function : Warning< @@ -741,6 +751,12 @@ def err_attribute_weak_static : Error< "weak declaration of '%0' must be public">; def warn_attribute_weak_import_invalid_on_definition : Warning< "'weak_import' attribute cannot be specified on a definition">; +def err_attribute_weakref_not_static : Error< + "weakref declaration of '%0' must be static">; +def err_attribute_weakref_not_global_context : Error< + "weakref declaration of '%0' must be in a global context">; +def err_attribute_weakref_without_alias : Error< + "weakref declaration of '%0' must also have an alias attribute">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{function|union|" "variable and function|function or method|parameter|" @@ -846,8 +862,10 @@ def err_attribute_regparm_invalid_number : Error< // Clang-Specific Attributes def err_attribute_iboutlet : Error< - "'iboutlet' attribute can only be applied to instance variables or " + "iboutlet attribute can only be applied to instance variables or " "properties">; +def err_attribute_ibaction: Error< + "ibaction attribute can only be applied to Objective-C instance methods">; def err_attribute_overloadable_not_function : Error< "'overloadable' attribute can only be applied to a function">; def err_attribute_overloadable_missing : Error< @@ -1482,6 +1500,8 @@ def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; +def err_misplaced_ivar : Error<"ivar may be placed in a class extension " + "in non-fragile-abi2 mode only">; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; @@ -1572,6 +1592,8 @@ def err_indirect_goto_in_protected_scope : Error< def err_addr_of_label_in_protected_scope : Error< "address taken of label in protected scope, jump to it would have " "unknown effect on scope">; +def note_protected_by_variable_init : Note< + "jump bypasses variable initialization">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla : Note< @@ -1761,7 +1783,8 @@ def err_typecheck_incomplete_array_needs_initializer : Error< def err_array_init_not_init_list : Error< "array initializer must be an initializer " "list%select{| or string literal}0">; - +def warn_deprecated_string_literal_conversion : Warning< + "conversion from string literal to %0 is deprecated">; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; @@ -1777,6 +1800,11 @@ def err_unqualified_pointer_member_function : Error< "must explicitly qualify member function %0 when taking its address">; def err_typecheck_invalid_lvalue_addrof : Error< "address expression must be an lvalue or a function designator">; +def ext_typecheck_addrof_class_temporary : ExtWarn< + "taking the address of a temporary object of type %0">, + InGroup<DiagGroup<"address-of-temporary">>, DefaultError; +def err_typecheck_addrof_class_temporary : Error< + "taking the address of a temporary object of type %0">; def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; def err_typecheck_indirection_requires_pointer : Error< @@ -1807,6 +1835,9 @@ def ext_typecheck_cond_incompatible_operands : ExtWarn< "incompatible operand types (%0 and %1)">; def err_typecheck_comparison_of_distinct_pointers : Error< "comparison of distinct pointer types (%0 and %1)">; +def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn< + "comparison of distinct pointer types (%0 and %1) uses non-standard " + "composite pointer type %2">; def err_typecheck_vector_comparison : Error< "comparison of vector types (%0 and %1) not supported yet">; def err_typecheck_assign_const : Error<"read-only variable is not assignable">; @@ -1992,6 +2023,9 @@ def err_new_array_nonconst : Error< "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_placement_new_non_placement_delete : Error< + "'new' expression with placement arguments refers to non-placement " + "'operator delete'">; def err_array_size_not_integral : Error< "array size expression must have integral or enumerated type, not %0">; def err_default_init_const : Error< @@ -2057,7 +2091,12 @@ def err_pseudo_dtor_call_with_args : Error< def err_dtor_expr_without_call : Error< "%select{destructor reference|pseudo-destructor expression}0 must be " "called immediately with '()'">; - +def err_pseudo_dtor_destructor_non_type : Error< + "%0 does not refer to a type name in pseudo-destructor expression; expected " + "the name of type %1">; +def err_pseudo_dtor_template : Error< + "specialization of template %0 does not refer to a scalar type in pseudo-" + "destructor expression">; def err_invalid_use_of_function_type : Error< "a function type is not allowed here">; def err_invalid_use_of_array_type : Error<"an array type is not allowed here">; @@ -2226,6 +2265,9 @@ def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< "incompatible operand types (%0 and %1)">; +def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn< + "incompatible operand types (%0 and %1) use non-standard composite pointer " + "type %2">; def err_cast_selector_expr : Error< "cannot type cast @selector expression">; def warn_typecheck_cond_incompatible_pointers : ExtWarn< @@ -2486,8 +2528,8 @@ def warn_printf_write_back : Warning< InGroup<FormatSecurity>; def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup<Format>; -def warn_printf_too_many_data_args : Warning< - "more data arguments than format specifiers">, InGroup<FormatExtraArgs>; +def warn_printf_data_arg_not_used : Warning< + "data argument not used by format string">, InGroup<FormatExtraArgs>; def warn_printf_invalid_conversion : Warning< "invalid conversion specifier '%0'">, InGroup<Format>; def warn_printf_incomplete_specifier : Warning< @@ -2497,6 +2539,15 @@ def warn_printf_missing_format_string : Warning< def warn_printf_conversion_argument_type_mismatch : Warning< "conversion specifies type %0 but the argument has type %1">, InGroup<Format>; +def warn_printf_zero_positional_specifier : Warning< + "position arguments in format strings start counting at 1 (not 0)">, + InGroup<Format>; +def warn_printf_invalid_positional_specifier : Warning< + "invalid position specified for %select{field width|field precision}0">, + InGroup<Format>; +def warn_printf_mix_positional_nonpositional_args : Warning< + "cannot mix positional and non-positional arguments in format string">, + InGroup<Format>; def warn_null_arg : Warning< "null passed to a callee which requires a non-null argument">, InGroup<NonNull>; @@ -2506,15 +2557,10 @@ def warn_printf_format_string_is_wide_literal : Warning< "format string should not be a wide string">, InGroup<Format>; def warn_printf_format_string_contains_null_char : Warning< "format string contains '\\0' within the string body">, InGroup<Format>; -def warn_printf_asterisk_width_missing_arg : Warning< - "'*' specified field width is missing a matching 'int' argument">; -def warn_printf_asterisk_precision_missing_arg : Warning< - "'.*' specified field precision is missing a matching 'int' argument">; -def warn_printf_asterisk_width_wrong_type : Warning< - "field width should have type %0, but argument has type %1">, - InGroup<Format>; -def warn_printf_asterisk_precision_wrong_type : Warning< - "field precision should have type %0, but argument has type %1">, +def warn_printf_asterisk_missing_arg : Warning< + "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">; +def warn_printf_asterisk_wrong_type : Warning< + "field %select{width|precision}0 should have type %1, but argument has type %2">, InGroup<Format>; def warn_printf_nonsensical_precision: Warning< "precision used in '%0' conversion specifier (where it has no meaning)">, @@ -2571,7 +2617,8 @@ def err_case_not_in_switch : Error<"'case' statement not in switch statement">; def warn_bool_switch_condition : Warning< "switch condition is a bool">; def warn_case_value_overflow : Warning< - "overflow converting case value to switch condition type (%0 to %1)">; + "overflow converting case value to switch condition type (%0 to %1)">, + InGroup<DiagGroup<"switch">>; def err_duplicate_case : Error<"duplicate case value '%0'">; def warn_case_empty_range : Warning<"empty case range specified">; def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">, @@ -2695,6 +2742,8 @@ def ext_c99_array_usage : Extension< def err_c99_array_usage_cxx : Error< "C99-specific array features are not permitted in C++">; +def note_getter_unavailable : Note< + "or because setter is declared here, but no getter method %0 is found">; def err_invalid_protocol_qualifiers : Error< "invalid protocol qualifiers on non-ObjC type">; def warn_ivar_use_hidden : Warning< diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index d909f83..23e6efe 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -59,7 +59,6 @@ public: unsigned POSIXThreads : 1; // Compiling with POSIX thread support // (-pthread) unsigned Blocks : 1; // block extension to C - unsigned BlockIntrospection: 1; // block have ObjC type encodings. unsigned EmitAllDecls : 1; // Emit all declarations, even if // they are unused. unsigned MathErrno : 1; // Math functions must respect errno @@ -143,7 +142,6 @@ public: ThreadsafeStatics = 1; POSIXThreads = 0; Blocks = 0; - BlockIntrospection = 0; EmitAllDecls = 0; MathErrno = 1; @@ -156,7 +154,7 @@ public: OverflowChecking = 0; ObjCGCBitmapPrint = 0; - InstantiationDepth = 99; + InstantiationDepth = 500; Optimize = 0; OptimizeSize = 0; diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 9b50e8d..2019e27 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -38,6 +38,13 @@ inline void Emit16(llvm::raw_ostream& Out, uint32_t V) { assert((V >> 16) == 0); } +inline void Emit24(llvm::raw_ostream& Out, uint32_t V) { + Out << (unsigned char)(V); + Out << (unsigned char)(V >> 8); + Out << (unsigned char)(V >> 16); + assert((V >> 24) == 0); +} + inline void Emit32(llvm::raw_ostream& Out, uint32_t V) { Out << (unsigned char)(V); Out << (unsigned char)(V >> 8); diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index d498044..2401a72 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -147,12 +147,22 @@ public: void addTransition(const GRState *state) { assert(state); + // If the 'state' is not new, we need to check if the cached state 'ST' + // is new. if (state != getState() || (ST && ST != B.GetState(Pred))) GenerateNode(state, true); else Dst.Add(Pred); } + // Generate a node with a new program point different from the one that will + // be created by the GRStmtNodeBuilder. + void addTransition(const GRState *state, ProgramPoint Loc) { + ExplodedNode *N = B.generateNode(Loc, state, Pred); + if (N) + addTransition(N); + } + void EmitReport(BugReport *R) { Eng.getBugReporter().EmitReport(R); } diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 6da4581..c5bf513 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -40,6 +40,8 @@ class GRCoreEngine { friend class GRIndirectGotoNodeBuilder; friend class GRSwitchNodeBuilder; friend class GREndPathNodeBuilder; + friend class GRCallEnterNodeBuilder; + friend class GRCallExitNodeBuilder; GRSubEngine& SubEngine; @@ -67,6 +69,9 @@ class GRCoreEngine { void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, ExplodedNode* Pred); + void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, + unsigned Index, ExplodedNode *Pred); + void HandleCallExit(const CallExit &L, ExplodedNode *Pred); /// Get the initial state from the subengine. const GRState* getInitialState(const LocationContext *InitLoc) { @@ -90,6 +95,9 @@ class GRCoreEngine { void ProcessSwitch(GRSwitchNodeBuilder& Builder); + void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); + void ProcessCallExit(GRCallExitNodeBuilder &Builder); + private: GRCoreEngine(const GRCoreEngine&); // Do not implement. GRCoreEngine& operator=(const GRCoreEngine&); @@ -130,7 +138,6 @@ class GRStmtNodeBuilder { CFGBlock& B; const unsigned Idx; ExplodedNode* Pred; - ExplodedNode* LastNode; GRStateManager& Mgr; GRAuditor* Auditor; @@ -157,10 +164,6 @@ public: ExplodedNode* getBasePredecessor() const { return Pred; } - ExplodedNode* getLastNode() const { - return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL; - } - // FIXME: This should not be exposed. GRWorkList *getWorkList() { return Eng.WList; } @@ -194,6 +197,12 @@ public: return generateNode(S, St, Pred, PointKind); } + ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, + ExplodedNode* Pred) { + HasGeneratedNode = true; + return generateNodeInternal(PP, State, Pred); + } + ExplodedNode* generateNodeInternal(const ProgramPoint &PP, const GRState* State, ExplodedNode* Pred); @@ -431,6 +440,8 @@ public: ExplodedNode* generateNode(const GRState* State, const void *tag = 0, ExplodedNode *P = 0); + void GenerateCallExitNode(const GRState *state); + CFGBlock* getBlock() const { return &B; } const GRState* getState() const { @@ -438,6 +449,60 @@ public: } }; +class GRCallEnterNodeBuilder { + GRCoreEngine &Eng; + + const ExplodedNode *Pred; + + // The call site. + const Stmt *CE; + + // The definition of callee. + const FunctionDecl *FD; + + // The parent block of the CallExpr. + const CFGBlock *Block; + + // The CFGBlock index of the CallExpr. + unsigned Index; + +public: + GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, + const Stmt *s, const FunctionDecl *fd, + const CFGBlock *blk, unsigned idx) + : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} + + const GRState *getState() const { return Pred->getState(); } + + const LocationContext *getLocationContext() const { + return Pred->getLocationContext(); + } + + const Stmt *getCallExpr() const { return CE; } + + const FunctionDecl *getCallee() const { return FD; } + + const CFGBlock *getBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + + void GenerateNode(const GRState *state, const LocationContext *LocCtx); +}; + +class GRCallExitNodeBuilder { + GRCoreEngine &Eng; + const ExplodedNode *Pred; + +public: + GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred) + : Eng(eng), Pred(pred) {} + + const ExplodedNode *getPredecessor() const { return Pred; } + + const GRState *getState() const { return Pred->getState(); } + + void GenerateNode(const GRState *state); +}; } // end clang namespace #endif diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 90a2cd5..763bbcc 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -171,7 +171,13 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. void ProcessEndPath(GREndPathNodeBuilder& builder); - + + // Generate the entry node of the callee. + void ProcessCallEnter(GRCallEnterNodeBuilder &builder); + + // Generate the first post callsite node. + void ProcessCallExit(GRCallExitNodeBuilder &builder); + /// EvalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 4e44697..9194ee8 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -16,25 +16,24 @@ // FIXME: Reduce the number of includes. +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Checker/PathSensitive/ConstraintManager.h" #include "clang/Checker/PathSensitive/Environment.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/Store.h" -#include "clang/Checker/PathSensitive/ConstraintManager.h" #include "clang/Checker/PathSensitive/ValueManager.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/ASTContext.h" -#include "clang/Analysis/Analyses/LiveVariables.h" -#include "llvm/Support/Casting.h" -#include "llvm/System/DataTypes.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" - +#include "llvm/System/DataTypes.h" #include <functional> namespace clang { @@ -77,16 +76,13 @@ public: typedef llvm::ImmutableMap<void*, void*> GenericDataMap; private: - void operator=(const GRState& R) const; + void operator=(const GRState& R) const; // Do not implement. friend class GRStateManager; GRStateManager *StateMgr; Environment Env; Store St; - - // FIXME: Make these private. -public: GenericDataMap GDM; public: diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index ce57c2c..f2cd048 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -28,6 +28,8 @@ class GRBranchNodeBuilder; class GRIndirectGotoNodeBuilder; class GRSwitchNodeBuilder; class GREndPathNodeBuilder; +class GRCallEnterNodeBuilder; +class GRCallExitNodeBuilder; class LocationContext; class GRSubEngine { @@ -64,6 +66,12 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0; + + // Generate the entry node of the callee. + virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0; + + // Generate the first post callsite node. + virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; /// EvalAssume - Called by ConstraintManager. Used to call checker-specific /// logic for handling assumptions on symbolic values. diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 12bc0b7..be89d2a 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -428,7 +428,6 @@ public: /// which correspond to "code+data". The distinction is important, because /// like a closure a block captures the values of externally referenced /// variables. -/// BlockDataRegion - A region that represents code texts of blocks (closures). class BlockDataRegion : public SubRegion { friend class MemRegionManager; const BlockTextRegion *BC; @@ -798,11 +797,10 @@ class MemRegionManager { GlobalsSpaceRegion *globals; - const StackFrameContext *cachedStackLocalsFrame; - StackLocalsSpaceRegion *cachedStackLocalsRegion; - - const StackFrameContext *cachedStackArgumentsFrame; - StackArgumentsSpaceRegion *cachedStackArgumentsRegion; + llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> + StackLocalsSpaceRegions; + llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> + StackArgumentsSpaceRegions; HeapSpaceRegion *heap; UnknownSpaceRegion *unknown; @@ -810,10 +808,7 @@ class MemRegionManager { public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), - cachedStackLocalsFrame(0), cachedStackLocalsRegion(0), - cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0), - heap(0), unknown(0), code(0) {} + : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {} ~MemRegionManager(); diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index 8eb3196..d49f5e8 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -89,27 +89,23 @@ public: typedef const SymbolData* SymbolRef; +// A symbol representing the value of a MemRegion. class SymbolRegionValue : public SymbolData { - const MemRegion *R; - // We may cast the region to another type, so the expected type of the symbol - // may be different from the region's original type. - QualType T; + const TypedRegion *R; public: - SymbolRegionValue(SymbolID sym, const MemRegion *r, QualType t = QualType()) - : SymbolData(RegionValueKind, sym), R(r), T(t) {} + SymbolRegionValue(SymbolID sym, const TypedRegion *r) + : SymbolData(RegionValueKind, sym), R(r) {} - const MemRegion* getRegion() const { return R; } + const TypedRegion* getRegion() const { return R; } - static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R, - QualType T) { + static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) { profile.AddInteger((unsigned) RegionValueKind); profile.AddPointer(R); - T.Profile(profile); } virtual void Profile(llvm::FoldingSetNodeID& profile) { - Profile(profile, R, T); + Profile(profile, R); } void dumpToStream(llvm::raw_ostream &os) const; @@ -122,6 +118,7 @@ public: } }; +// A symbol representing the result of an expression. class SymbolConjured : public SymbolData { const Stmt* S; QualType T; @@ -161,6 +158,8 @@ public: } }; +// A symbol representing the value of a MemRegion whose parent region has +// symbolic value. class SymbolDerived : public SymbolData { SymbolRef parentSymbol; const TypedRegion *R; @@ -294,8 +293,8 @@ public: static bool canSymbolicate(QualType T); /// Make a unique symbol for MemRegion R according to its kind. - const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R, - QualType T = QualType()); + const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R); + const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, unsigned VisitCount, const void* SymbolTag = 0); diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h index ea3af57..f80ad42 100644 --- a/include/clang/Checker/PathSensitive/ValueManager.h +++ b/include/clang/Checker/PathSensitive/ValueManager.h @@ -94,8 +94,7 @@ public: DefinedOrUnknownSVal makeZeroVal(QualType T); /// getRegionValueSymbolVal - make a unique symbol for value of R. - DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R, - QualType T = QualType()); + DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R); DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, const Expr *E, unsigned Count); diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index e1d4ad1..e0e0f77 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -53,6 +53,8 @@ public: unsigned UnwindTables : 1; /// Emit unwind tables. unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. + unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker + /// aliases to base ctors when possible. /// The code model to use (-mcmodel). std::string CodeModel; @@ -101,6 +103,7 @@ public: UnrollLoops = 0; UnwindTables = 0; VerifyModule = 1; + CXXCtorDtorAliases = 0; Inlining = NoInlining; RelocationModel = "pic"; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 047363e..7cd26ef 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -143,6 +143,8 @@ def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, HelpText<"Generate unwinding tables for all functions">; +def mconstructor_aliases : Flag<"-mconstructor-aliases">, + HelpText<"Emit complete constructors and destructors as aliases when possible">; def O : Joined<"-O">, HelpText<"Optimization level">; def Os : Flag<"-Os">, HelpText<"Optimize for size">; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 64f88ed..59c3946 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -70,6 +70,9 @@ public: /// Default name for linked images (e.g., "a.out"). std::string DefaultImageName; + /// Driver title to use with help. + std::string DriverTitle; + /// Host information for the platform the driver is running as. This /// will generally be the actual host platform, but not always. const HostInfo *Host; @@ -137,6 +140,9 @@ public: void setCheckInputsExist(bool Value) { CheckInputsExist = Value; } + const std::string &getTitle() { return DriverTitle; } + void setTitle(std::string Value) { DriverTitle = Value; } + /// @} /// @name Primary Functionality /// @{ diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 4693e5c..b462a4d 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -235,7 +235,6 @@ def fastcp : Flag<"-fastcp">, Group<f_Group>; def fastf : Flag<"-fastf">, Group<f_Group>; def fast : Flag<"-fast">, Group<f_Group>; def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>; -def fblock_introspection : Flag<"-fblock-introspection">, Group<f_Group>; def fblocks : Flag<"-fblocks">, Group<f_Group>; def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; @@ -445,7 +444,7 @@ def multiply__defined : Separate<"-multiply_defined">; def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>; def m_Separate : Separate<"-m">, Group<m_Group>; def m_Joined : Joined<"-m">, Group<m_Group>; -def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[DriverOption, HelpHidden]>, +def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>, HelpText<"Use relative instead of canonical paths">; def no_cpp_precomp : Flag<"-no-cpp-precomp">; def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 3a343b3..d933230 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -80,6 +80,10 @@ namespace types { /// getCompilationPhase - Return the \args N th compilation phase to /// be done for this type. phases::ID getCompilationPhase(ID Id, unsigned N); + + /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given + /// C type (used for clang++ emulation of g++ behaviour) + ID lookupCXXTypeForCType(ID Id); } // end namespace types } // end namespace driver diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 7ec5063..b5b09f5 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -69,26 +69,6 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile, const LangOptions &LOpts, bool SilenceRewriteMacroWarning); -// LLVM code generator: uses the code generation backend to generate LLVM -// assembly. This runs optimizations depending on the CodeGenOptions -// parameter. The output depends on the Action parameter. -enum BackendAction { - Backend_EmitAssembly, // Emit native assembly files - Backend_EmitBC, // Emit LLVM bitcode files - Backend_EmitLL, // Emit human-readable LLVM assembly - Backend_EmitNothing, // Don't emit anything (benchmarking mode) - Backend_EmitObj // Emit native object files -}; -ASTConsumer *CreateBackendConsumer(BackendAction Action, - Diagnostic &Diags, - const LangOptions &Features, - const CodeGenOptions &CodeGenOpts, - const TargetOptions &TargetOpts, - bool TimePasses, - const std::string &ModuleID, - llvm::raw_ostream *OS, - llvm::LLVMContext& C); - /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to /// HTML with syntax highlighting suitable for viewing in a web-browser. ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP, diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index f122dd9..626a162 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -18,6 +18,8 @@ #include "llvm/ADT/OwningPtr.h" #include "clang/Basic/FileManager.h" #include "clang/Index/ASTLocation.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/System/Path.h" #include <string> #include <vector> #include <cassert> @@ -51,7 +53,6 @@ class ASTUnit { llvm::OwningPtr<TargetInfo> Target; llvm::OwningPtr<Preprocessor> PP; llvm::OwningPtr<ASTContext> Ctx; - bool tempFile; /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. @@ -80,6 +81,14 @@ class ASTUnit { // Critical optimization when using clang_getCursor(). ASTLocation LastLoc; + /// \brief The set of diagnostics produced when creating this + /// translation unit. + llvm::SmallVector<StoredDiagnostic, 4> Diagnostics; + + /// \brief Temporary files that should be removed when the ASTUnit is + /// destroyed. + llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles; + ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT @@ -104,8 +113,13 @@ public: const std::string &getOriginalSourceFileName(); const std::string &getPCHFileName(); - void unlinkTemporaryFile() { tempFile = true; } - + /// \brief Add a temporary file that the ASTUnit depends on. + /// + /// This file will be erased when the ASTUnit is destroyed. + void addTemporaryFile(const llvm::sys::Path &TempFile) { + TemporaryFiles.push_back(TempFile); + } + bool getOnlyLocalDecls() const { return OnlyLocalDecls; } void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } @@ -120,6 +134,15 @@ public: return TopLevelDecls; } + // Retrieve the diagnostics associated with this AST + typedef const StoredDiagnostic * diag_iterator; + diag_iterator diag_begin() const { return Diagnostics.begin(); } + diag_iterator diag_end() const { return Diagnostics.end(); } + unsigned diag_size() const { return Diagnostics.size(); } + llvm::SmallVector<StoredDiagnostic, 4> &getDiagnostics() { + return Diagnostics; + } + /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; @@ -136,7 +159,8 @@ public: Diagnostic &Diags, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, - unsigned NumRemappedFiles = 0); + unsigned NumRemappedFiles = 0, + bool CaptureDiagnostics = false); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a /// CompilerInvocation object. @@ -151,7 +175,8 @@ public: // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, Diagnostic &Diags, - bool OnlyLocalDecls = false); + bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -173,7 +198,8 @@ public: llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, - unsigned NumRemappedFiles = 0); + unsigned NumRemappedFiles = 0, + bool CaptureDiagnostics = false); }; } // namespace clang diff --git a/include/clang/Frontend/CodeGenAction.h b/include/clang/Frontend/CodeGenAction.h new file mode 100644 index 0000000..a1e3c42 --- /dev/null +++ b/include/clang/Frontend/CodeGenAction.h @@ -0,0 +1,65 @@ +//===--- CodeGenAction.h - LLVM Code Generation Frontend Action -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/ADT/OwningPtr.h" + +namespace llvm { + class Module; +} + +namespace clang { + +class CodeGenAction : public ASTFrontendAction { +private: + unsigned Act; + llvm::OwningPtr<llvm::Module> TheModule; + +protected: + CodeGenAction(unsigned _Act); + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual void EndSourceFileAction(); + +public: + ~CodeGenAction(); + + /// takeModule - Take the generated LLVM module, for use after the action has + /// been run. The result may be null on failure. + llvm::Module *takeModule(); +}; + +class EmitAssemblyAction : public CodeGenAction { +public: + EmitAssemblyAction(); +}; + +class EmitBCAction : public CodeGenAction { +public: + EmitBCAction(); +}; + +class EmitLLVMAction : public CodeGenAction { +public: + EmitLLVMAction(); +}; + +class EmitLLVMOnlyAction : public CodeGenAction { +public: + EmitLLVMOnlyAction(); +}; + +class EmitObjAction : public CodeGenAction { +public: + EmitObjAction(); +}; + +} diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index cbb3508..5348e6b 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -159,46 +159,6 @@ public: }; //===----------------------------------------------------------------------===// -// Code Gen AST Actions -//===----------------------------------------------------------------------===// - -class CodeGenAction : public ASTFrontendAction { -private: - unsigned Act; - -protected: - CodeGenAction(unsigned _Act); - - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - -class EmitAssemblyAction : public CodeGenAction { -public: - EmitAssemblyAction(); -}; - -class EmitBCAction : public CodeGenAction { -public: - EmitBCAction(); -}; - -class EmitLLVMAction : public CodeGenAction { -public: - EmitLLVMAction(); -}; - -class EmitLLVMOnlyAction : public CodeGenAction { -public: - EmitLLVMOnlyAction(); -}; - -class EmitObjAction : public CodeGenAction { -public: - EmitObjAction(); -}; - -//===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index e22d37b..d4014b3 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -524,7 +524,9 @@ namespace clang { /// associates a declaration name with one or more declaration /// IDs. This data is used when performing qualified name lookup /// into a DeclContext via DeclContext::lookup. - DECL_CONTEXT_VISIBLE + DECL_CONTEXT_VISIBLE, + /// \brief A NamespaceDecl record. + DECL_NAMESPACE }; /// \brief Record codes for each kind of statement or expression. diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index d727e48..d09e51f 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -37,11 +37,19 @@ class TextDiagnosticPrinter : public DiagnosticClient { unsigned LastCaretDiagnosticWasNote : 1; unsigned OwnsOutputStream : 1; + /// A string to prefix to error messages. + std::string Prefix; + public: TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags, bool OwnsOutputStream = false); virtual ~TextDiagnosticPrinter(); + /// setPrefix - Set the diagnostic printer prefix string, which will be + /// printed at the start of any diagnostics. If empty, no prefix string is + /// used. + void setPrefix(std::string Value) { Prefix = Value; } + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { LangOpts = &LO; } diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index dedbbd8..db9c884 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -570,6 +570,12 @@ public: /// if an internal buffer is returned. unsigned getSpelling(const Token &Tok, const char *&Buffer) const; + /// getSpelling - This method is used to get the spelling of a token into a + /// SmallVector. Note that the returned StringRef may not point to the + /// supplied buffer if a copy can be avoided. + llvm::StringRef getSpelling(const Token &Tok, + llvm::SmallVectorImpl<char> &Buffer) const; + /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant /// with length 1, return the character. char getSpellingOfSingleCharacterNumericConstant(const Token &Tok) const { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index ec542f0..f211b5c 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -327,13 +327,26 @@ public: return false; } + /// \brief Determine whether the given name refers to a non-type nested name + /// specifier, e.g., the name of a namespace or namespace alias. + /// + /// This actual is used in the parsing of pseudo-destructor names to + /// distinguish a nested-name-specifier and a "type-name ::" when we + /// see the token sequence "X :: ~". + virtual bool isNonTypeNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, + SourceLocation IdLoc, + IdentifierInfo &II, + TypeTy *ObjectType) { + return false; + } + /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the /// global scope ('::'). virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc) { return 0; } - + /// \brief Parsed an identifier followed by '::' in a C++ /// nested-name-specifier. /// @@ -490,6 +503,12 @@ public: return; } + /// \brief Note that the given declaration had an initializer that could not + /// be parsed. + virtual void ActOnInitializerError(DeclPtrTy Dcl) { + return; + } + /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this /// gives the actions implementation a chance to process the group as a whole. virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, @@ -1075,7 +1094,7 @@ public: SourceLocation RLoc) { return ExprEmpty(); } - + /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref]) /// of the form \c x.m or \c p->m. /// @@ -1473,6 +1492,18 @@ public: //===------------------------- C++ Expressions --------------------------===// + /// \brief Parsed a destructor name or pseudo-destructor name. + /// + /// \returns the type being destructed. + virtual TypeTy *getDestructorName(SourceLocation TildeLoc, + IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, const CXXScopeSpec &SS, + TypeTy *ObjectType, + bool EnteringContext) { + return getTypeName(II, NameLoc, S, &SS, false, ObjectType); + } + + /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, @@ -1594,12 +1625,66 @@ public: /// with the type into which name lookup should look to find the member in /// the member access expression. /// + /// \param MayBePseudoDestructor Originally false. The action should + /// set this true if the expression may end up being a + /// pseudo-destructor expression, indicating to the parser that it + /// shoudl be parsed as a pseudo-destructor rather than as a member + /// access expression. Note that this should apply both when the + /// object type is a scalar and when the object type is dependent. + /// /// \returns the (possibly modified) \p Base expression virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, - TypeTy *&ObjectType) { + TypeTy *&ObjectType, + bool &MayBePseudoDestructor) { + return ExprEmpty(); + } + + /// \brief Parsed a C++ pseudo-destructor expression or a dependent + /// member access expression that has the same syntactic form as a + /// pseudo-destructor expression. + /// + /// \param S The scope in which the member access expression occurs. + /// + /// \param Base The expression in which a member is being accessed, e.g., the + /// "x" in "x.f". + /// + /// \param OpLoc The location of the member access operator ("." or "->") + /// + /// \param OpKind The kind of member access operator ("." or "->") + /// + /// \param SS The nested-name-specifier that precedes the type names + /// in the grammar. Note that this nested-name-specifier will not + /// cover the last "type-name ::" in the grammar, because it isn't + /// necessarily a nested-name-specifier. + /// + /// \param FirstTypeName The type name that follows the optional + /// nested-name-specifier but precedes the '::', e.g., the first + /// type-name in "type-name :: type-name". This type name may be + /// empty. This will be either an identifier or a template-id. + /// + /// \param CCLoc The location of the '::' in "type-name :: + /// typename". May be invalid, if there is no \p FirstTypeName. + /// + /// \param TildeLoc The location of the '~'. + /// + /// \param SecondTypeName The type-name following the '~', which is + /// the name of the type being destroyed. This will be either an + /// identifier or a template-id. + /// + /// \param HasTrailingLParen Whether the next token in the stream is + /// a left parentheses. + virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen) { return ExprEmpty(); } diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index ecaa6ae..37acab9 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -51,7 +51,8 @@ public: AttributeList *Next, bool declspec = false, bool cxx0x = false); ~AttributeList(); - enum Kind { // Please keep this list alphabetized. + enum Kind { // Please keep this list alphabetized. + AT_IBAction, // Clang-specific. AT_IBOutlet, // Clang-specific. AT_address_space, AT_alias, @@ -88,8 +89,10 @@ public: AT_nsobject, AT_objc_exception, AT_override, - AT_cf_returns_retained, // Clang-specific. - AT_ns_returns_retained, // Clang-specific. + AT_cf_returns_not_retained, // Clang-specific. + AT_cf_returns_retained, // Clang-specific. + AT_ns_returns_not_retained, // Clang-specific. + AT_ns_returns_retained, // Clang-specific. AT_objc_gc, AT_overloadable, // Clang-specific. AT_packed, @@ -106,6 +109,7 @@ public: AT_visibility, AT_warn_unused_result, AT_weak, + AT_weakref, AT_weak_import, AT_reqd_wg_size, IgnoredAttribute, diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f4d3d3e..f034aa1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -320,86 +320,39 @@ private: /// This returns true if the token was annotated. bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false); - /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but only - /// annotates C++ scope specifiers. This returns true if the token was - /// annotated. + /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but + /// only annotates C++ scope specifiers. This returns true if there + /// was an unrecoverable error. bool TryAnnotateCXXScopeToken(bool EnteringContext = false); /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens, /// replacing them with the non-context-sensitive keywords. This returns /// true if the token was replaced. bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc, - const char *&PrevSpec, unsigned &DiagID, bool &isInvalid) { - if (getLang().AltiVec) { - if (Tok.getIdentifierInfo() == Ident_vector) { - const Token nextToken = NextToken(); - switch (nextToken.getKind()) { - case tok::kw_short: - case tok::kw_long: - case tok::kw_signed: - case tok::kw_unsigned: - case tok::kw_void: - case tok::kw_char: - case tok::kw_int: - case tok::kw_float: - case tok::kw_double: - case tok::kw_bool: - case tok::kw___pixel: - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); - return true; - case tok::identifier: - if (nextToken.getIdentifierInfo() == Ident_pixel) { - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); - return true; - } - break; - default: - break; - } - } else if ((Tok.getIdentifierInfo() == Ident_pixel) && - DS.isTypeAltiVecVector()) { - isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); - return true; - } - } - return false; + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid) { + if (!getLang().AltiVec || + (Tok.getIdentifierInfo() != Ident_vector && + Tok.getIdentifierInfo() != Ident_pixel)) + return false; + + return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid); } /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector /// identifier token, replacing it with the non-context-sensitive __vector. /// This returns true if the token was replaced. bool TryAltiVecVectorToken() { - if (getLang().AltiVec) { - if (Tok.getIdentifierInfo() == Ident_vector) { - const Token nextToken = NextToken(); - switch (nextToken.getKind()) { - case tok::kw_short: - case tok::kw_long: - case tok::kw_signed: - case tok::kw_unsigned: - case tok::kw_void: - case tok::kw_char: - case tok::kw_int: - case tok::kw_float: - case tok::kw_double: - case tok::kw_bool: - case tok::kw___pixel: - Tok.setKind(tok::kw___vector); - return true; - case tok::identifier: - if (nextToken.getIdentifierInfo() == Ident_pixel) { - Tok.setKind(tok::kw___vector); - return true; - } - break; - default: - break; - } - } - } - return false; + if (!getLang().AltiVec || + Tok.getIdentifierInfo() != Ident_vector) return false; + return TryAltiVecVectorTokenOutOfLine(); } - + + bool TryAltiVecVectorTokenOutOfLine(); + bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid); + /// TentativeParsingAction - An object that is used as a kind of "tentative /// parsing transaction". It gets instantiated to mark the token position and /// after the token consumption is done, Commit() or Revert() is called to @@ -849,6 +802,7 @@ private: DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, AttributeList *prefixAttrs = 0); void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind visibility, SourceLocation atLoc); bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P, llvm::SmallVectorImpl<SourceLocation> &PLocs, @@ -962,7 +916,8 @@ private: bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, TypeTy *ObjectType, - bool EnteringContext); + bool EnteringContext, + bool *MayBePseudoDestructor = 0); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Casts @@ -973,6 +928,13 @@ private: OwningExprResult ParseCXXTypeid(); //===--------------------------------------------------------------------===// + // C++ 5.2.4: C++ Pseudo-Destructor Expressions + OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + Action::TypeTy *ObjectType); + + //===--------------------------------------------------------------------===// // C++ 9.3.2: C++ 'this' pointer OwningExprResult ParseCXXThis(); @@ -1153,7 +1115,7 @@ private: void ParseObjCTypeQualifierList(ObjCDeclSpec &DS); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, - AccessSpecifier AS = AS_none); + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none); void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); @@ -1172,6 +1134,11 @@ private: bool isDeclarationSpecifier(); bool isTypeSpecifierQualifier(); bool isTypeQualifier() const; + + /// isKnownToBeTypeSpecifier - Return true if we know that the specified token + /// is definitely a type-specifier. Return false if it isn't part of a type + /// specifier or if we're not sure. + bool isKnownToBeTypeSpecifier(const Token &Tok) const; /// isDeclarationStatement - Disambiguates between a declaration or an /// expression statement, when parsing function bodies. @@ -1387,8 +1354,7 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. TypeResult ParseClassName(SourceLocation &EndLocation, - const CXXScopeSpec *SS = 0, - bool DestrExpected = false); + const CXXScopeSpec *SS = 0); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1414,7 +1380,8 @@ private: SourceLocation NameLoc, bool EnteringContext, TypeTy *ObjectType, - UnqualifiedId &Id); + UnqualifiedId &Id, + bool AssumeTemplateId = false); bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, TypeTy *ObjectType, UnqualifiedId &Result); diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h index c6a1e53..c9825f6 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Parse/Scope.h @@ -129,6 +129,9 @@ private: typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy; UsingDirectivesTy UsingDirectives; + /// \brief The number of errors at the start of the given scope. + unsigned NumErrorsAtStart; + public: Scope(Scope *Parent, unsigned ScopeFlags) { Init(Parent, ScopeFlags); @@ -208,6 +211,14 @@ public: void* getEntity() const { return Entity; } void setEntity(void *E) { Entity = E; } + /// \brief Retrieve the number of errors that had been emitted when we + /// entered this scope. + unsigned getNumErrorsAtStart() const { return NumErrorsAtStart; } + + void setNumErrorsAtStart(unsigned NumErrors) { + NumErrorsAtStart = NumErrors; + } + /// isClassScope - Return true if this scope is a class/struct/union scope. bool isClassScope() const { return (getFlags() & Scope::ClassScope); @@ -300,6 +311,7 @@ public: DeclsInScope.clear(); UsingDirectives.clear(); Entity = 0; + NumErrorsAtStart = 0; } }; |