diff options
Diffstat (limited to 'contrib/llvm/tools/clang/include')
238 files changed, 21085 insertions, 8020 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h index 1320145..13ba6ba 100644 --- a/contrib/llvm/tools/clang/include/clang-c/Index.h +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -35,6 +35,16 @@ extern "C" { #define CINDEX_LINKAGE #endif +#ifdef __GNUC__ + #define CINDEX_DEPRECATED __attribute__((deprecated)) +#else + #ifdef _MSC_VER + #define CINDEX_DEPRECATED __declspec(deprecated) + #else + #define CINDEX_DEPRECATED + #endif +#endif + /** \defgroup CINDEX libclang: C Interface to Clang * * The C Interface to Clang provides a relatively small API that exposes @@ -204,6 +214,61 @@ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, */ CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); +typedef enum { + /** + * \brief Used to indicate that no special CXIndex options are needed. + */ + CXGlobalOpt_None = 0x0, + + /** + * \brief Used to indicate that threads that libclang creates for indexing + * purposes should use background priority. + * Affects \see clang_indexSourceFile, \see clang_indexTranslationUnit, + * \see clang_parseTranslationUnit, \see clang_saveTranslationUnit. + */ + CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1, + + /** + * \brief Used to indicate that threads that libclang creates for editing + * purposes should use background priority. + * Affects \see clang_reparseTranslationUnit, \see clang_codeCompleteAt, + * \see clang_annotateTokens + */ + CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2, + + /** + * \brief Used to indicate that all threads that libclang creates should use + * background priority. + */ + CXGlobalOpt_ThreadBackgroundPriorityForAll = + CXGlobalOpt_ThreadBackgroundPriorityForIndexing | + CXGlobalOpt_ThreadBackgroundPriorityForEditing + +} CXGlobalOptFlags; + +/** + * \brief Sets general options associated with a CXIndex. + * + * For example: + * \code + * CXIndex idx = ...; + * clang_CXIndex_setGlobalOptions(idx, + * clang_CXIndex_getGlobalOptions(idx) | + * CXGlobalOpt_ThreadBackgroundPriorityForIndexing); + * \endcode + * + * \param options A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags. + */ +CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options); + +/** + * \brief Gets the general options associated with a CXIndex. + * + * \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that + * are associated with the given CXIndex object. + */ +CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex); + /** * \defgroup CINDEX_FILES File manipulation routines * @@ -522,6 +587,86 @@ enum CXDiagnosticSeverity { typedef void *CXDiagnostic; /** + * \brief A group of CXDiagnostics. + */ +typedef void *CXDiagnosticSet; + +/** + * \brief Determine the number of diagnostics in a CXDiagnosticSet. + */ +CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags); + +/** + * \brief Retrieve a diagnostic associated with the given CXDiagnosticSet. + * + * \param Unit the CXDiagnosticSet 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_getDiagnosticInSet(CXDiagnosticSet Diags, + unsigned Index); + + +/** + * \brief Describes the kind of error that occurred (if any) in a call to + * \c clang_loadDiagnostics. + */ +enum CXLoadDiag_Error { + /** + * \brief Indicates that no error occurred. + */ + CXLoadDiag_None = 0, + + /** + * \brief Indicates that an unknown error occurred while attempting to + * deserialize diagnostics. + */ + CXLoadDiag_Unknown = 1, + + /** + * \brief Indicates that the file containing the serialized diagnostics + * could not be opened. + */ + CXLoadDiag_CannotLoad = 2, + + /** + * \brief Indicates that the serialized diagnostics file is invalid or + * corrupt. + */ + CXLoadDiag_InvalidFile = 3 +}; + +/** + * \brief Deserialize a set of diagnostics from a Clang diagnostics bitcode + * file. + * + * \param The name of the file to deserialize. + * \param A pointer to a enum value recording if there was a problem + * deserializing the diagnostics. + * \param A pointer to a CXString for recording the error string + * if the file was not successfully loaded. + * + * \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These + * diagnostics should be released using clang_disposeDiagnosticSet(). + */ +CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file, + enum CXLoadDiag_Error *error, + CXString *errorString); + +/** + * \brief Release a CXDiagnosticSet and all of its contained diagnostics. + */ +CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags); + +/** + * \brief Retrieve the child diagnostics of a CXDiagnostic. This + * CXDiagnosticSet does not need to be released by clang_diposeDiagnosticSet. + */ +CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D); + +/** * \brief Determine the number of diagnostics produced for the given * translation unit. */ @@ -540,6 +685,15 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index); /** + * \brief Retrieve the complete set of diagnostics associated with a + * translation unit. + * + * \param Unit the translation unit to query. + */ +CINDEX_LINKAGE CXDiagnosticSet + clang_getDiagnosticSetFromTU(CXTranslationUnit Unit); + +/** * \brief Destroy a diagnostic. */ CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); @@ -686,14 +840,25 @@ CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag, CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic); /** - * \brief Retrieve the name of a particular diagnostic category. + * \brief Retrieve the name of a particular diagnostic category. This + * is now deprecated. Use clang_getDiagnosticCategoryText() + * instead. * * \param Category A diagnostic category number, as returned by * \c clang_getDiagnosticCategory(). * * \returns The name of the given diagnostic category. */ -CINDEX_LINKAGE CXString clang_getDiagnosticCategoryName(unsigned Category); +CINDEX_DEPRECATED CINDEX_LINKAGE +CXString clang_getDiagnosticCategoryName(unsigned Category); + +/** + * \brief Retrieve the diagnostic category text for a given diagnostic. + * + * + * \returns The text of the given diagnostic category. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic); /** * \brief Determine the number of source ranges associated with the given @@ -905,27 +1070,15 @@ enum CXTranslationUnit_Flags { * we are testing C++ precompiled preamble support. It is deprecated. */ CXTranslationUnit_CXXChainedPCH = 0x20, - - /** - * \brief Used to indicate that the "detailed" preprocessing record, - * if requested, should also contain nested macro expansions. - * - * Nested macro expansions (i.e., macro expansions that occur - * inside another macro expansion) can, in some code bases, require - * a large amount of storage to due preprocessor metaprogramming. Moreover, - * its fairly rare that this information is useful for libclang clients. - */ - CXTranslationUnit_NestedMacroExpansions = 0x40, /** - * \brief Legacy name to indicate that the "detailed" preprocessing record, - * if requested, should contain nested macro expansions. + * \brief Used to indicate that function/method bodies should be skipped while + * parsing. * - * \see CXTranslationUnit_NestedMacroExpansions for the current name for this - * value, and its semantics. This is just an alias. + * This option can be used to search for declarations/definitions while + * ignoring the usages. */ - CXTranslationUnit_NestedMacroInstantiations = - CXTranslationUnit_NestedMacroExpansions + CXTranslationUnit_SkipFunctionBodies = 0x40 }; /** @@ -1411,7 +1564,13 @@ enum CXCursorKind { */ CXCursor_OverloadedDeclRef = 49, - CXCursor_LastRef = CXCursor_OverloadedDeclRef, + /** + * \brief A reference to a variable that occurs in some non-expression + * context, e.g., a C++ lambda capture list. + */ + CXCursor_VariableRef = 50, + + CXCursor_LastRef = CXCursor_VariableRef, /* Error conditions */ CXCursor_FirstInvalid = 70, @@ -1528,7 +1687,7 @@ enum CXCursorKind { */ CXCursor_StmtExpr = 121, - /** \brief Represents a C1X generic selection. + /** \brief Represents a C11 generic selection. */ CXCursor_GenericSelectionExpr = 122, @@ -1605,19 +1764,19 @@ enum CXCursorKind { */ CXCursor_UnaryExpr = 136, - /** \brief ObjCStringLiteral, used for Objective-C string literals i.e. "foo". + /** \brief An Objective-C string literal i.e. @"foo". */ CXCursor_ObjCStringLiteral = 137, - /** \brief ObjCEncodeExpr, used for in Objective-C. + /** \brief An Objective-C @encode expression. */ CXCursor_ObjCEncodeExpr = 138, - /** \brief ObjCSelectorExpr used for in Objective-C. + /** \brief An Objective-C @selector expression. */ CXCursor_ObjCSelectorExpr = 139, - /** \brief Objective-C's protocol expression. + /** \brief An Objective-C @protocol expression. */ CXCursor_ObjCProtocolExpr = 140, @@ -1657,7 +1816,25 @@ enum CXCursorKind { */ CXCursor_SizeOfPackExpr = 143, - CXCursor_LastExpr = CXCursor_SizeOfPackExpr, + /* \brief Represents a C++ lambda expression that produces a local function + * object. + * + * \code + * void abssort(float *x, unsigned N) { + * std::sort(x, x + N, + * [](float a, float b) { + * return std::abs(a) < std::abs(b); + * }); + * } + * \endcode + */ + CXCursor_LambdaExpr = 144, + + /** \brief Objective-c Boolean Literal. + */ + CXCursor_ObjCBoolLiteralExpr = 145, + + CXCursor_LastExpr = CXCursor_ObjCBoolLiteralExpr, /* Statements */ CXCursor_FirstStmt = 200, @@ -1744,7 +1921,7 @@ enum CXCursorKind { */ CXCursor_AsmStmt = 215, - /** \brief Objective-C's overall @try-@catc-@finall statement. + /** \brief Objective-C's overall @try-@catch-@finally statement. */ CXCursor_ObjCAtTryStmt = 216, @@ -1831,7 +2008,8 @@ enum CXCursorKind { CXCursor_CXXFinalAttr = 404, CXCursor_CXXOverrideAttr = 405, CXCursor_AnnotateAttr = 406, - CXCursor_LastAttr = CXCursor_AnnotateAttr, + CXCursor_AsmLabelAttr = 407, + CXCursor_LastAttr = CXCursor_AsmLabelAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -1894,7 +2072,7 @@ CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor); /** * \brief Returns non-zero if \arg cursor is null. */ -int clang_Cursor_isNull(CXCursor); +CINDEX_LINKAGE int clang_Cursor_isNull(CXCursor); /** * \brief Compute a hash value for the given cursor. @@ -2126,11 +2304,12 @@ CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor); * In both Objective-C and C++, a method (aka virtual member function, * in C++) can override a virtual method in a base class. For * Objective-C, a method is said to override any method in the class's - * interface (if we're coming from an implementation), its protocols, - * or its categories, that has the same selector and is of the same - * kind (class or instance). If no such method exists, the search - * continues to the class's superclass, its protocols, and its - * categories, and so on. + * base class, its protocols, or its categories' protocols, that has the same + * selector and is of the same kind (class or instance). + * If no such method exists, the search continues to the class's superclass, + * its protocols, and its categories, and so on. A method from an Objective-C + * implementation is considered to override the same methods as its + * corresponding method in the interface. * * For C++, a virtual member function overrides any virtual member * function with the same signature that occurs in its base @@ -2303,9 +2482,28 @@ enum CXTypeKind { CXType_ObjCObjectPointer = 109, CXType_FunctionNoProto = 110, CXType_FunctionProto = 111, - CXType_ConstantArray = 112 + CXType_ConstantArray = 112, + CXType_Vector = 113 +}; + +/** + * \brief Describes the calling convention of a function type + */ +enum CXCallingConv { + CXCallingConv_Default = 0, + CXCallingConv_C = 1, + CXCallingConv_X86StdCall = 2, + CXCallingConv_X86FastCall = 3, + CXCallingConv_X86ThisCall = 4, + CXCallingConv_X86Pascal = 5, + CXCallingConv_AAPCS = 6, + CXCallingConv_AAPCS_VFP = 7, + + CXCallingConv_Invalid = 100, + CXCallingConv_Unexposed = 200 }; + /** * \brief The type of an element in the abstract syntax tree. * @@ -2321,6 +2519,58 @@ typedef struct { CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C); /** + * \brief Retrieve the underlying type of a typedef declaration. + * + * If the cursor does not reference a typedef declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C); + +/** + * \brief Retrieve the integer type of an enum declaration. + * + * If the cursor does not reference an enum declaration, an invalid type is + * returned. + */ +CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C); + +/** + * \brief Retrieve the integer value of an enum constant declaration as a signed + * long long. + * + * If the cursor does not reference an enum constant declaration, LLONG_MIN is returned. + * Since this is also potentially a valid constant value, the kind of the cursor + * must be verified before calling this function. + */ +CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C); + +/** + * \brief Retrieve the integer value of an enum constant declaration as an unsigned + * long long. + * + * If the cursor does not reference an enum constant declaration, ULLONG_MAX is returned. + * Since this is also potentially a valid constant value, the kind of the cursor + * must be verified before calling this function. + */ +CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C); + +/** + * \brief Retrieve the number of non-variadic arguments associated with a given + * cursor. + * + * If a cursor that is not a function or method is passed in, -1 is returned. + */ +CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C); + +/** + * \brief Retrieve the argument cursor of a function or method. + * + * If a cursor that is not a function or method is passed in or the index + * exceeds the number of arguments, an invalid cursor is returned. + */ +CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i); + +/** * \determine Determine whether two CXTypes represent the same type. * * \returns non-zero if the CXTypes represent the same type and @@ -2378,13 +2628,44 @@ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C); CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); /** + * \brief Retrieve the calling convention associated with a function type. + * + * If a non-function type is passed in, CXCallingConv_Invalid is returned. + */ +CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T); + +/** * \brief Retrieve the result type associated with a function type. + * + * If a non-function type is passed in, an invalid type is returned. */ CINDEX_LINKAGE CXType clang_getResultType(CXType T); /** - * \brief Retrieve the result type associated with a given cursor. This only - * returns a valid type of the cursor refers to a function or method. + * \brief Retrieve the number of non-variadic arguments associated with a function type. + * + * If a non-function type is passed in, -1 is returned. + */ +CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); + +/** + * \brief Retrieve the type of an argument of a function type. + * + * If a non-function type is passed in or the function does not have enough parameters, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i); + +/** + * \brief Return 1 if the CXType is a variadic function type, and 0 otherwise. + * + */ +CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T); + +/** + * \brief Retrieve the result type associated with a given cursor. + * + * This only returns a valid type if the cursor refers to a function or method. */ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); @@ -2395,6 +2676,22 @@ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); CINDEX_LINKAGE unsigned clang_isPODType(CXType T); /** + * \brief Return the element type of an array, complex, or vector type. + * + * If a type is passed in that is not an array, complex, or vector type, + * an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_getElementType(CXType T); + +/** + * \brief Return the number of elements of an array or vector type. + * + * If a type is passed in that is not an array or vector type, + * -1 is returned. + */ +CINDEX_LINKAGE long long clang_getNumElements(CXType T); + +/** * \brief Return the element type of an array type. * * If a non-array type is passed in, an invalid type is returned. @@ -2653,6 +2950,21 @@ CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property, CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); /** + * \brief Retrieve a range for a piece that forms the cursors spelling name. + * Most of the times there is only one range for the complete spelling but for + * objc methods and objc message expressions, there are multiple pieces for each + * selector identifier. + * + * \param pieceIndex the index of the spelling name piece. If this is greater + * than the actual number of pieces, it will return a NULL (invalid) range. + * + * \param options Reserved. + */ +CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor, + unsigned pieceIndex, + unsigned options); + +/** * \brief Retrieve the display name for the entity referenced by this cursor. * * The display name contains extra information that helps identify the cursor, @@ -2735,6 +3047,20 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); */ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor); + +/** + * \brief If the cursor points to a selector identifier in a objc method or + * message expression, this returns the selector index. + * + * After getting a cursor with \see clang_getCursor, this can be called to + * determine if the location points to a selector identifier. + * + * \returns The selector index if the cursor is an objc method or message + * expression and the cursor is pointing to a selector identifier, or -1 + * otherwise. + */ +CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor); + /** * @} */ @@ -3347,6 +3673,26 @@ clang_getCompletionAnnotation(CXCompletionString completion_string, unsigned annotation_number); /** + * \brief Retrieve the parent context of the given completion string. + * + * The parent context of a completion string is the semantic parent of + * the declaration (if any) that the code completion represents. For example, + * a code completion for an Objective-C method would have the method's class + * or protocol as its context. + * + * \param completion_string The code completion string whose parent is + * being queried. + * + * \param kind If non-NULL, will be set to the kind of the parent context, + * or CXCursor_NotImplemented if there is no context. + * + * \param Returns the name of the completion parent, e.g., "NSObject" if + * the completion string represents a method in the NSObject class. + */ +CINDEX_LINKAGE CXString +clang_getCompletionParent(CXCompletionString completion_string, + enum CXCursorKind *kind); +/** * \brief Retrieve a completion string for an arbitrary declaration or macro * definition cursor. * @@ -3788,6 +4134,20 @@ typedef void *CXRemapping; CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path); /** + * \brief Retrieve a remapping. + * + * \param filePaths pointer to an array of file paths containing remapping info. + * + * \param numFiles number of file paths. + * + * \returns the requested remapping. This remapping must be freed + * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred. + */ +CINDEX_LINKAGE +CXRemapping clang_getRemappingsFromFileList(const char **filePaths, + unsigned numFiles); + +/** * \brief Determine the number of remappings. */ CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping); @@ -3856,6 +4216,524 @@ void clang_findReferencesInFileWithBlock(CXCursor, CXFile, #endif /** + * \brief The client's data object that is associated with a CXFile. + */ +typedef void *CXIdxClientFile; + +/** + * \brief The client's data object that is associated with a semantic entity. + */ +typedef void *CXIdxClientEntity; + +/** + * \brief The client's data object that is associated with a semantic container + * of entities. + */ +typedef void *CXIdxClientContainer; + +/** + * \brief The client's data object that is associated with an AST file (PCH + * or module). + */ +typedef void *CXIdxClientASTFile; + +/** + * \brief Source location passed to index callbacks. + */ +typedef struct { + void *ptr_data[2]; + unsigned int_data; +} CXIdxLoc; + +/** + * \brief Data for \see ppIncludedFile callback. + */ +typedef struct { + /** + * \brief Location of '#' in the #include/#import directive. + */ + CXIdxLoc hashLoc; + /** + * \brief Filename as written in the #include/#import directive. + */ + const char *filename; + /** + * \brief The actual file that the #include/#import directive resolved to. + */ + CXFile file; + int isImport; + int isAngled; +} CXIdxIncludedFileInfo; + +/** + * \brief Data for \see importedASTFile callback. + */ +typedef struct { + CXFile file; + /** + * \brief Location where the file is imported. It is useful mostly for + * modules. + */ + CXIdxLoc loc; + /** + * \brief Non-zero if the AST file is a module otherwise it's a PCH. + */ + int isModule; +} CXIdxImportedASTFileInfo; + +typedef enum { + CXIdxEntity_Unexposed = 0, + CXIdxEntity_Typedef = 1, + CXIdxEntity_Function = 2, + CXIdxEntity_Variable = 3, + CXIdxEntity_Field = 4, + CXIdxEntity_EnumConstant = 5, + + CXIdxEntity_ObjCClass = 6, + CXIdxEntity_ObjCProtocol = 7, + CXIdxEntity_ObjCCategory = 8, + + CXIdxEntity_ObjCInstanceMethod = 9, + CXIdxEntity_ObjCClassMethod = 10, + CXIdxEntity_ObjCProperty = 11, + CXIdxEntity_ObjCIvar = 12, + + CXIdxEntity_Enum = 13, + CXIdxEntity_Struct = 14, + CXIdxEntity_Union = 15, + + CXIdxEntity_CXXClass = 16, + CXIdxEntity_CXXNamespace = 17, + CXIdxEntity_CXXNamespaceAlias = 18, + CXIdxEntity_CXXStaticVariable = 19, + CXIdxEntity_CXXStaticMethod = 20, + CXIdxEntity_CXXInstanceMethod = 21, + CXIdxEntity_CXXConstructor = 22, + CXIdxEntity_CXXDestructor = 23, + CXIdxEntity_CXXConversionFunction = 24, + CXIdxEntity_CXXTypeAlias = 25 + +} CXIdxEntityKind; + +typedef enum { + CXIdxEntityLang_None = 0, + CXIdxEntityLang_C = 1, + CXIdxEntityLang_ObjC = 2, + CXIdxEntityLang_CXX = 3 +} CXIdxEntityLanguage; + +/** + * \brief Extra C++ template information for an entity. This can apply to: + * CXIdxEntity_Function + * CXIdxEntity_CXXClass + * CXIdxEntity_CXXStaticMethod + * CXIdxEntity_CXXInstanceMethod + * CXIdxEntity_CXXConstructor + * CXIdxEntity_CXXConversionFunction + * CXIdxEntity_CXXTypeAlias + */ +typedef enum { + CXIdxEntity_NonTemplate = 0, + CXIdxEntity_Template = 1, + CXIdxEntity_TemplatePartialSpecialization = 2, + CXIdxEntity_TemplateSpecialization = 3 +} CXIdxEntityCXXTemplateKind; + +typedef enum { + CXIdxAttr_Unexposed = 0, + CXIdxAttr_IBAction = 1, + CXIdxAttr_IBOutlet = 2, + CXIdxAttr_IBOutletCollection = 3 +} CXIdxAttrKind; + +typedef struct { + CXIdxAttrKind kind; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxAttrInfo; + +typedef struct { + CXIdxEntityKind kind; + CXIdxEntityCXXTemplateKind templateKind; + CXIdxEntityLanguage lang; + const char *name; + const char *USR; + CXCursor cursor; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; +} CXIdxEntityInfo; + +typedef struct { + CXCursor cursor; +} CXIdxContainerInfo; + +typedef struct { + const CXIdxAttrInfo *attrInfo; + const CXIdxEntityInfo *objcClass; + CXCursor classCursor; + CXIdxLoc classLoc; +} CXIdxIBOutletCollectionAttrInfo; + +typedef struct { + const CXIdxEntityInfo *entityInfo; + CXCursor cursor; + CXIdxLoc loc; + const CXIdxContainerInfo *semanticContainer; + /** + * \brief Generally same as \see semanticContainer but can be different in + * cases like out-of-line C++ member functions. + */ + const CXIdxContainerInfo *lexicalContainer; + int isRedeclaration; + int isDefinition; + int isContainer; + const CXIdxContainerInfo *declAsContainer; + /** + * \brief Whether the declaration exists in code or was created implicitly + * by the compiler, e.g. implicit objc methods for properties. + */ + int isImplicit; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; +} CXIdxDeclInfo; + +typedef enum { + CXIdxObjCContainer_ForwardRef = 0, + CXIdxObjCContainer_Interface = 1, + CXIdxObjCContainer_Implementation = 2 +} CXIdxObjCContainerKind; + +typedef struct { + const CXIdxDeclInfo *declInfo; + CXIdxObjCContainerKind kind; +} CXIdxObjCContainerDeclInfo; + +typedef struct { + const CXIdxEntityInfo *base; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxBaseClassInfo; + +typedef struct { + const CXIdxEntityInfo *protocol; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxObjCProtocolRefInfo; + +typedef struct { + const CXIdxObjCProtocolRefInfo *const *protocols; + unsigned numProtocols; +} CXIdxObjCProtocolRefListInfo; + +typedef struct { + const CXIdxObjCContainerDeclInfo *containerInfo; + const CXIdxBaseClassInfo *superInfo; + const CXIdxObjCProtocolRefListInfo *protocols; +} CXIdxObjCInterfaceDeclInfo; + +typedef struct { + const CXIdxObjCContainerDeclInfo *containerInfo; + const CXIdxEntityInfo *objcClass; + CXCursor classCursor; + CXIdxLoc classLoc; + const CXIdxObjCProtocolRefListInfo *protocols; +} CXIdxObjCCategoryDeclInfo; + +typedef struct { + const CXIdxDeclInfo *declInfo; + const CXIdxEntityInfo *getter; + const CXIdxEntityInfo *setter; +} CXIdxObjCPropertyDeclInfo; + +typedef struct { + const CXIdxDeclInfo *declInfo; + const CXIdxBaseClassInfo *const *bases; + unsigned numBases; +} CXIdxCXXClassDeclInfo; + +/** + * \brief Data for \see indexEntityReference callback. + */ +typedef enum { + /** + * \brief The entity is referenced directly in user's code. + */ + CXIdxEntityRef_Direct = 1, + /** + * \brief An implicit reference, e.g. a reference of an ObjC method via the + * dot syntax. + */ + CXIdxEntityRef_Implicit = 2 +} CXIdxEntityRefKind; + +/** + * \brief Data for \see indexEntityReference callback. + */ +typedef struct { + CXIdxEntityRefKind kind; + /** + * \brief Reference cursor. + */ + CXCursor cursor; + CXIdxLoc loc; + /** + * \brief The entity that gets referenced. + */ + const CXIdxEntityInfo *referencedEntity; + /** + * \brief Immediate "parent" of the reference. For example: + * + * \code + * Foo *var; + * \endcode + * + * The parent of reference of type 'Foo' is the variable 'var'. + * For references inside statement bodies of functions/methods, + * the parentEntity will be the function/method. + */ + const CXIdxEntityInfo *parentEntity; + /** + * \brief Lexical container context of the reference. + */ + const CXIdxContainerInfo *container; +} CXIdxEntityRefInfo; + +typedef struct { + /** + * \brief Called periodically to check whether indexing should be aborted. + * Should return 0 to continue, and non-zero to abort. + */ + int (*abortQuery)(CXClientData client_data, void *reserved); + + /** + * \brief Called at the end of indexing; passes the complete diagnostic set. + */ + void (*diagnostic)(CXClientData client_data, + CXDiagnosticSet, void *reserved); + + CXIdxClientFile (*enteredMainFile)(CXClientData client_data, + CXFile mainFile, void *reserved); + + /** + * \brief Called when a file gets #included/#imported. + */ + CXIdxClientFile (*ppIncludedFile)(CXClientData client_data, + const CXIdxIncludedFileInfo *); + + /** + * \brief Called when a AST file (PCH or module) gets imported. + * + * AST files will not get indexed (there will not be callbacks to index all + * the entities in an AST file). The recommended action is that, if the AST + * file is not already indexed, to block further indexing and initiate a new + * indexing job specific to the AST file. + */ + CXIdxClientASTFile (*importedASTFile)(CXClientData client_data, + const CXIdxImportedASTFileInfo *); + + /** + * \brief Called at the beginning of indexing a translation unit. + */ + CXIdxClientContainer (*startedTranslationUnit)(CXClientData client_data, + void *reserved); + + void (*indexDeclaration)(CXClientData client_data, + const CXIdxDeclInfo *); + + /** + * \brief Called to index a reference of an entity. + */ + void (*indexEntityReference)(CXClientData client_data, + const CXIdxEntityRefInfo *); + +} IndexerCallbacks; + +CINDEX_LINKAGE int clang_index_isEntityObjCContainerKind(CXIdxEntityKind); +CINDEX_LINKAGE const CXIdxObjCContainerDeclInfo * +clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCInterfaceDeclInfo * +clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE +const CXIdxObjCCategoryDeclInfo * +clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCProtocolRefListInfo * +clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxObjCPropertyDeclInfo * +clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *); + +CINDEX_LINKAGE const CXIdxIBOutletCollectionAttrInfo * +clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *); + +CINDEX_LINKAGE const CXIdxCXXClassDeclInfo * +clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *); + +/** + * \brief For retrieving a custom CXIdxClientContainer attached to a + * container. + */ +CINDEX_LINKAGE CXIdxClientContainer +clang_index_getClientContainer(const CXIdxContainerInfo *); + +/** + * \brief For setting a custom CXIdxClientContainer attached to a + * container. + */ +CINDEX_LINKAGE void +clang_index_setClientContainer(const CXIdxContainerInfo *,CXIdxClientContainer); + +/** + * \brief For retrieving a custom CXIdxClientEntity attached to an entity. + */ +CINDEX_LINKAGE CXIdxClientEntity +clang_index_getClientEntity(const CXIdxEntityInfo *); + +/** + * \brief For setting a custom CXIdxClientEntity attached to an entity. + */ +CINDEX_LINKAGE void +clang_index_setClientEntity(const CXIdxEntityInfo *, CXIdxClientEntity); + +/** + * \brief An indexing action, to be applied to one or multiple translation units + * but not on concurrent threads. If there are threads doing indexing + * concurrently, they should use different CXIndexAction objects. + */ +typedef void *CXIndexAction; + +/** + * \brief An indexing action, to be applied to one or multiple translation units + * but not on concurrent threads. If there are threads doing indexing + * concurrently, they should use different CXIndexAction objects. + * + * \param CIdx The index object with which the index action will be associated. + */ +CINDEX_LINKAGE CXIndexAction clang_IndexAction_create(CXIndex CIdx); + +/** + * \brief Destroy the given index action. + * + * The index action must not be destroyed until all of the translation units + * created within that index action have been destroyed. + */ +CINDEX_LINKAGE void clang_IndexAction_dispose(CXIndexAction); + +typedef enum { + /** + * \brief Used to indicate that no special indexing options are needed. + */ + CXIndexOpt_None = 0x0, + + /** + * \brief Used to indicate that \see indexEntityReference should be invoked + * for only one reference of an entity per source file that does not also + * include a declaration/definition of the entity. + */ + CXIndexOpt_SuppressRedundantRefs = 0x1, + + /** + * \brief Function-local symbols should be indexed. If this is not set + * function-local symbols will be ignored. + */ + CXIndexOpt_IndexFunctionLocalSymbols = 0x2, + + /** + * \brief Implicit function/class template instantiations should be indexed. + * If this is not set, implicit instantiations will be ignored. + */ + CXIndexOpt_IndexImplicitTemplateInstantiations = 0x4, + + /** + * \brief Suppress all compiler warnings when parsing for indexing. + */ + CXIndexOpt_SuppressWarnings = 0x8 +} CXIndexOptFlags; + +/** + * \brief Index the given source file and the translation unit corresponding + * to that file via callbacks implemented through \see IndexerCallbacks. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the invoked callbacks. + * + * \param index_callbacks Pointer to indexing callbacks that the client + * implements. + * + * \param index_callbacks_size Size of \see IndexerCallbacks structure that gets + * passed in index_callbacks. + * + * \param index_options A bitmask of options that affects how indexing is + * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags. + * + * \param out_TU [out] pointer to store a CXTranslationUnit that can be reused + * after indexing is finished. Set to NULL if you do not require it. + * + * \returns If there is a failure from which the there is no recovery, returns + * non-zero, otherwise returns 0. + * + * The rest of the parameters are the same as \see clang_parseTranslationUnit. + */ +CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction, + CXClientData client_data, + IndexerCallbacks *index_callbacks, + unsigned index_callbacks_size, + unsigned index_options, + const char *source_filename, + const char * const *command_line_args, + int num_command_line_args, + struct CXUnsavedFile *unsaved_files, + unsigned num_unsaved_files, + CXTranslationUnit *out_TU, + unsigned TU_options); + +/** + * \brief Index the given translation unit via callbacks implemented through + * \see IndexerCallbacks. + * + * The order of callback invocations is not guaranteed to be the same as + * when indexing a source file. The high level order will be: + * + * -Preprocessor callbacks invocations + * -Declaration/reference callbacks invocations + * -Diagnostic callback invocations + * + * The parameters are the same as \see clang_indexSourceFile. + * + * \returns If there is a failure from which the there is no recovery, returns + * non-zero, otherwise returns 0. + */ +CINDEX_LINKAGE int clang_indexTranslationUnit(CXIndexAction, + CXClientData client_data, + IndexerCallbacks *index_callbacks, + unsigned index_callbacks_size, + unsigned index_options, + CXTranslationUnit); + +/** + * \brief Retrieve the CXIdxFile, file, line, column, and offset represented by + * the given CXIdxLoc. + * + * If the location refers into a macro expansion, retrieves the + * location of the macro expansion and if it refers into a macro argument + * retrieves the location of the argument. + */ +CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc, + CXIdxClientFile *indexFile, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * \brief Retrieve the CXSourceLocation represented by the given CXIdxLoc. + */ +CINDEX_LINKAGE +CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc); + +/** * @} */ diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h index d8dea0b..86a6cbb 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h @@ -37,7 +37,7 @@ namespace arcmt { /// /// \returns false if no error is produced, true otherwise. bool checkForManualIssues(CompilerInvocation &CI, - StringRef Filename, InputKind Kind, + const FrontendInputFile &Input, DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors = false, StringRef plistOut = StringRef()); @@ -47,7 +47,7 @@ bool checkForManualIssues(CompilerInvocation &CI, /// /// \returns false if no error is produced, true otherwise. bool applyTransformations(CompilerInvocation &origCI, - StringRef Filename, InputKind Kind, + const FrontendInputFile &Input, DiagnosticConsumer *DiagClient); /// \brief Applies automatic modifications and produces temporary files @@ -62,7 +62,7 @@ bool applyTransformations(CompilerInvocation &origCI, /// /// \returns false if no error is produced, true otherwise. bool migrateWithTemporaryFiles(CompilerInvocation &origCI, - StringRef Filename, InputKind Kind, + const FrontendInputFile &Input, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, @@ -76,9 +76,19 @@ bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap, StringRef outputDir, DiagnosticConsumer *DiagClient); +/// \brief Get the set of file remappings from a list of files with remapping +/// info. +/// +/// \returns false if no error is produced, true otherwise. +bool getFileRemappingsFromFileList( + std::vector<std::pair<std::string,std::string> > &remap, + ArrayRef<StringRef> remapFiles, + DiagnosticConsumer *DiagClient); + typedef void (*TransformFn)(MigrationPass &pass); -std::vector<TransformFn> getAllTransformations(); +std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode, + bool NoFinalizeRemoval); class MigrationProcess { CompilerInvocation OrigCI; diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h index 4eac4fa..e075252 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H #include "clang/Frontend/FrontendAction.h" +#include "clang/ARCMigrate/FileRemapper.h" #include "llvm/ADT/OwningPtr.h" namespace clang { @@ -32,6 +33,14 @@ public: ModifyAction(FrontendAction *WrappedAction); }; +class MigrateSourceAction : public ASTFrontendAction { + FileRemapper Remapper; +protected: + virtual bool BeginInvocation(CompilerInstance &CI); + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); +}; + class MigrateAction : public WrapperFrontendAction { std::string MigrateDir; std::string PlistOut; @@ -45,6 +54,23 @@ public: bool emitPremigrationARCErrors); }; +/// \brief Migrates to modern ObjC syntax. +class ObjCMigrateAction : public WrapperFrontendAction { + std::string MigrateDir; + bool MigrateLiterals; + bool MigrateSubscripting; + FileRemapper Remapper; + CompilerInstance *CompInst; +public: + ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, + bool migrateLiterals, + bool migrateSubscripting); + +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile); + virtual bool BeginInvocation(CompilerInstance &CI); +}; + } } diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h index 9a0b690..fe7cfad 100644 --- a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h +++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h @@ -24,13 +24,13 @@ namespace clang { class FileManager; class FileEntry; class DiagnosticsEngine; - class CompilerInvocation; + class PreprocessorOptions; namespace arcmt { class FileRemapper { // FIXME: Reuse the same FileManager for multiple ASTContexts. - llvm::OwningPtr<FileManager> FileMgr; + OwningPtr<FileManager> FileMgr; typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target; typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy; @@ -44,7 +44,10 @@ public: bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged); + bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag, + bool ignoreIfFilesChanged); bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag); + bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag); bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir = StringRef()); @@ -52,9 +55,9 @@ public: void remap(StringRef filePath, llvm::MemoryBuffer *memBuf); void remap(StringRef filePath, StringRef newPath); - void applyMappings(CompilerInvocation &CI) const; + void applyMappings(PreprocessorOptions &PPOpts) const; - void transferMappingsAndClear(CompilerInvocation &CI); + void transferMappingsAndClear(PreprocessorOptions &PPOpts); void clear(StringRef outputDir = StringRef()); diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h index 375af28..1b6e90c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/APValue.h +++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h @@ -17,14 +17,24 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" namespace clang { + class AddrLabelExpr; + class ASTContext; class CharUnits; class DiagnosticBuilder; class Expr; + class FieldDecl; + class Decl; + class ValueDecl; + class CXXRecordDecl; + class QualType; /// APValue - This class implements a discriminated union of [uninitialized] -/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. +/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], +/// [Vector: N * APValue], [Array: N * APValue] class APValue { typedef llvm::APSInt APSInt; typedef llvm::APFloat APFloat; @@ -36,8 +46,25 @@ public: ComplexInt, ComplexFloat, LValue, - Vector + Vector, + Array, + Struct, + Union, + MemberPointer, + AddrLabelDiff }; + typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; + typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; + union LValuePathEntry { + /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item + /// in the path. An opaque value of type BaseOrMemberType. + void *BaseOrMember; + /// ArrayIndex - The array index of the next item in the path. + uint64_t ArrayIndex; + }; + struct NoLValuePath {}; + struct UninitArray {}; + struct UninitStruct {}; private: ValueKind Kind; @@ -49,13 +76,37 @@ private: APFloat Real, Imag; ComplexAPFloat() : Real(0.0), Imag(0.0) {} }; - + struct LV; struct Vec { APValue *Elts; unsigned NumElts; Vec() : Elts(0), NumElts(0) {} ~Vec() { delete[] Elts; } }; + struct Arr { + APValue *Elts; + unsigned NumElts, ArrSize; + Arr(unsigned NumElts, unsigned ArrSize); + ~Arr(); + }; + struct StructData { + APValue *Elts; + unsigned NumBases; + unsigned NumFields; + StructData(unsigned NumBases, unsigned NumFields); + ~StructData(); + }; + struct UnionData { + const FieldDecl *Field; + APValue *Value; + UnionData(); + ~UnionData(); + }; + struct AddrLabelDiffData { + const AddrLabelExpr* LHSExpr; + const AddrLabelExpr* RHSExpr; + }; + struct MemberPointerData; enum { MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? @@ -84,18 +135,42 @@ public: APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { MakeComplexFloat(); setComplexFloat(R, I); } - APValue(const APValue &RHS) : Kind(Uninitialized) { - *this = RHS; + APValue(const APValue &RHS); + APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) + : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O, N, CallIndex); + } + APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, + bool OnePastTheEnd, unsigned CallIndex) + : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex); } - APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O); + APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { + MakeArray(InitElts, Size); + } + APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { + MakeStruct(B, M); + } + explicit APValue(const FieldDecl *D, const APValue &V = APValue()) + : Kind(Uninitialized) { + MakeUnion(); setUnion(D, V); + } + APValue(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { + MakeMemberPointer(Member, IsDerivedMember, Path); + } + APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) + : Kind(Uninitialized) { + MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); } - APValue(const Expr* B); ~APValue() { MakeUninit(); } + /// \brief Swaps the contents of this and the given APValue. + void swap(APValue &RHS); + ValueKind getKind() const { return Kind; } bool isUninit() const { return Kind == Uninitialized; } bool isInt() const { return Kind == Int; } @@ -104,9 +179,17 @@ public: bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } bool isVector() const { return Kind == Vector; } + bool isArray() const { return Kind == Array; } + bool isStruct() const { return Kind == Struct; } + bool isUnion() const { return Kind == Union; } + bool isMemberPointer() const { return Kind == MemberPointer; } + bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } - void print(raw_ostream &OS) const; void dump() const; + void dump(raw_ostream &OS) const; + + void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; + std::string getAsString(ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); @@ -124,19 +207,6 @@ public: return const_cast<APValue*>(this)->getFloat(); } - APValue &getVectorElt(unsigned i) { - assert(isVector() && "Invalid accessor"); - return ((Vec*)(char*)Data)->Elts[i]; - } - const APValue &getVectorElt(unsigned i) const { - assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const char*)Data)->Elts[i]; - } - unsigned getVectorLength() const { - assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data)->NumElts; - } - APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); return ((ComplexAPSInt*)(char*)Data)->Real; @@ -169,8 +239,104 @@ public: return const_cast<APValue*>(this)->getComplexFloatImag(); } - const Expr* getLValueBase() const; - CharUnits getLValueOffset() const; + const LValueBase getLValueBase() const; + CharUnits &getLValueOffset(); + const CharUnits &getLValueOffset() const { + return const_cast<APValue*>(this)->getLValueOffset(); + } + bool isLValueOnePastTheEnd() const; + bool hasLValuePath() const; + ArrayRef<LValuePathEntry> getLValuePath() const; + unsigned getLValueCallIndex() const; + + APValue &getVectorElt(unsigned I) { + assert(isVector() && "Invalid accessor"); + assert(I < getVectorLength() && "Index out of range"); + return ((Vec*)(char*)Data)->Elts[I]; + } + const APValue &getVectorElt(unsigned I) const { + return const_cast<APValue*>(this)->getVectorElt(I); + } + unsigned getVectorLength() const { + assert(isVector() && "Invalid accessor"); + return ((const Vec*)(const void *)Data)->NumElts; + } + + APValue &getArrayInitializedElt(unsigned I) { + assert(isArray() && "Invalid accessor"); + assert(I < getArrayInitializedElts() && "Index out of range"); + return ((Arr*)(char*)Data)->Elts[I]; + } + const APValue &getArrayInitializedElt(unsigned I) const { + return const_cast<APValue*>(this)->getArrayInitializedElt(I); + } + bool hasArrayFiller() const { + return getArrayInitializedElts() != getArraySize(); + } + APValue &getArrayFiller() { + assert(isArray() && "Invalid accessor"); + assert(hasArrayFiller() && "No array filler"); + return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()]; + } + const APValue &getArrayFiller() const { + return const_cast<APValue*>(this)->getArrayFiller(); + } + unsigned getArrayInitializedElts() const { + assert(isArray() && "Invalid accessor"); + return ((const Arr*)(const void *)Data)->NumElts; + } + unsigned getArraySize() const { + assert(isArray() && "Invalid accessor"); + return ((const Arr*)(const void *)Data)->ArrSize; + } + + unsigned getStructNumBases() const { + assert(isStruct() && "Invalid accessor"); + return ((const StructData*)(const char*)Data)->NumBases; + } + unsigned getStructNumFields() const { + assert(isStruct() && "Invalid accessor"); + return ((const StructData*)(const char*)Data)->NumFields; + } + APValue &getStructBase(unsigned i) { + assert(isStruct() && "Invalid accessor"); + return ((StructData*)(char*)Data)->Elts[i]; + } + APValue &getStructField(unsigned i) { + assert(isStruct() && "Invalid accessor"); + return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i]; + } + const APValue &getStructBase(unsigned i) const { + return const_cast<APValue*>(this)->getStructBase(i); + } + const APValue &getStructField(unsigned i) const { + return const_cast<APValue*>(this)->getStructField(i); + } + + const FieldDecl *getUnionField() const { + assert(isUnion() && "Invalid accessor"); + return ((const UnionData*)(const char*)Data)->Field; + } + APValue &getUnionValue() { + assert(isUnion() && "Invalid accessor"); + return *((UnionData*)(char*)Data)->Value; + } + const APValue &getUnionValue() const { + return const_cast<APValue*>(this)->getUnionValue(); + } + + const ValueDecl *getMemberPointerDecl() const; + bool isMemberPointerToDerivedMember() const; + ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; + + const AddrLabelExpr* getAddrLabelDiffLHS() const { + assert(isAddrLabelDiff() && "Invalid accessor"); + return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr; + } + const AddrLabelExpr* getAddrLabelDiffRHS() const { + assert(isAddrLabelDiff() && "Invalid accessor"); + return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr; + } void setInt(const APSInt &I) { assert(isInt() && "Invalid accessor"); @@ -201,12 +367,34 @@ public: ((ComplexAPFloat*)(char*)Data)->Real = R; ((ComplexAPFloat*)(char*)Data)->Imag = I; } - void setLValue(const Expr *B, const CharUnits &O); + void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, + unsigned CallIndex); + void setLValue(LValueBase B, const CharUnits &O, + ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, + unsigned CallIndex); + void setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData*)(char*)Data)->Field = Field; + *((UnionData*)(char*)Data)->Value = Value; + } + void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, + const AddrLabelExpr* RHSExpr) { + ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr; + ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr; + } - const APValue &operator=(const APValue &RHS); + /// Assign by swapping from a copy of the RHS. + APValue &operator=(APValue RHS) { + swap(RHS); + return *this; + } private: - void MakeUninit(); + void DestroyDataAndMakeUninit(); + void MakeUninit() { + if (Kind != Uninitialized) + DestroyDataAndMakeUninit(); + } void MakeInt() { assert(isUninit() && "Bad state change"); new ((void*)Data) APSInt(1); @@ -233,17 +421,26 @@ private: Kind = ComplexFloat; } void MakeLValue(); + void MakeArray(unsigned InitElts, unsigned Size); + void MakeStruct(unsigned B, unsigned M) { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) StructData(B, M); + Kind = Struct; + } + void MakeUnion() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) UnionData(); + Kind = Union; + } + void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path); + void MakeAddrLabelDiff() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) AddrLabelDiffData(); + Kind = AddrLabelDiff; + } }; -inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) { - V.print(OS); - return OS; -} - -// Writes a concise representation of V to DB, in a single << operation. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const APValue &V); - } // end namespace clang. #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h index fcc9176..69a3866 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h @@ -24,6 +24,7 @@ namespace clang { class SemaConsumer; // layering violation required for safe SemaConsumer class TagDecl; class VarDecl; + class FunctionDecl; /// ASTConsumer - This is an abstract interface that should be implemented by /// clients that read ASTs. This abstraction layer allows the client to be @@ -48,7 +49,9 @@ public: /// called by the parser to process every top-level Decl*. Note that D can be /// the head of a chain of Decls (e.g. for `int a, b` the chain will have two /// elements). Use Decl::getNextDeclarator() to walk the chain. - virtual void HandleTopLevelDecl(DeclGroupRef D); + /// + /// \returns true to continue parsing, or false to abort parsing. + virtual bool HandleTopLevelDecl(DeclGroupRef D); /// HandleInterestingDecl - Handle the specified interesting declaration. This /// is called by the AST reader when deserializing things that might interest @@ -65,6 +68,17 @@ public: /// can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) {} + /// \brief Invoked when a function is implicitly instantiated. + /// Note that at this point point it does not have a body, its body is + /// instantiated at the end of the translation unit and passed to + /// HandleTopLevelDecl. + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {} + + /// \brief Handle the specified top-level declaration that occurred inside + /// and ObjC container. + /// The default implementation ignored them. + virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); + /// CompleteTentativeDefinition - Callback invoked at the end of a translation /// unit to notify the consumer that the given tentative definition should be /// completed. @@ -76,6 +90,10 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this + // variable has been instantiated. + virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {} + /// \brief Callback involved at the end of a translation unit to /// notify the consumer that a vtable for the given C++ class is /// required. @@ -94,7 +112,9 @@ public: /// \brief If the consumer is interested in entities being deserialized from /// AST files, it should return a pointer to a ASTDeserializationListener here - virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; } + virtual ASTDeserializationListener *GetASTDeserializationListener() { + return 0; + } /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h index 48d7e94..96e41c5 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h @@ -21,17 +21,18 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/VersionTuple.h" #include "clang/AST/Decl.h" +#include "clang/AST/LambdaMangleContext.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" -#include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -55,6 +56,7 @@ namespace clang { class CXXABI; // Decls class DeclContext; + class CXXConversionDecl; class CXXMethodDecl; class CXXRecordDecl; class Decl; @@ -80,7 +82,7 @@ namespace clang { /// 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 : public llvm::RefCountedBase<ASTContext> { +class ASTContext : public RefCountedBase<ASTContext> { ASTContext &this_() { return *this; } mutable std::vector<Type*> Types; @@ -145,6 +147,11 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; + /// TypeInfoMap - A cache from types to size and alignment information. + typedef llvm::DenseMap<const Type*, + std::pair<uint64_t, unsigned> > TypeInfoMap; + mutable TypeInfoMap MemoizedTypeInfo; + /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions; @@ -202,12 +209,12 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { /// \brief The typedef for the predefined 'SEL' type. mutable TypedefDecl *ObjCSelDecl; - QualType ObjCProtoType; - const RecordType *ProtoStructType; - /// \brief The typedef for the predefined 'Class' type. mutable TypedefDecl *ObjCClassDecl; - + + /// \brief The typedef for the predefined 'Protocol' class in Objective-C. + mutable ObjCInterfaceDecl *ObjCProtocolClassDecl; + // Typedefs which may be provided defining the structure of Objective-C // pseudo-builtins QualType ObjCIdRedefinitionType; @@ -216,6 +223,8 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { QualType ObjCConstantStringType; mutable RecordDecl *CFConstantStringTypeDecl; + + QualType ObjCNSStringType; /// \brief The typedef declaration for the Objective-C "instancetype" type. TypedefDecl *ObjCInstanceTypeDecl; @@ -318,15 +327,22 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { /// 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. - typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector; + typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector; llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; + /// \brief Mapping from each declaration context to its corresponding lambda + /// mangling context. + llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts; + /// \brief Mapping that stores parameterIndex values for ParmVarDecls /// when that value exceeds the bitfield size of /// ParmVarDeclBits.ParameterIndex. typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable; ParameterIndexTable ParamIndices; + ImportDecl *FirstLocalImport; + ImportDecl *LastLocalImport; + TranslationUnitDecl *TUDecl; /// SourceMgr - The associated SourceManager object. @@ -346,7 +362,7 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { PartialDiagnostic::StorageAllocator DiagAllocator; /// \brief The current C++ ABI. - llvm::OwningPtr<CXXABI> ABI; + OwningPtr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); /// \brief The logical -> physical address space map. @@ -355,7 +371,8 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> { friend class ASTDeclReader; friend class ASTReader; friend class ASTWriter; - + friend class CXXRecordDecl; + const TargetInfo *Target; clang::PrintingPolicy PrintingPolicy; @@ -364,7 +381,7 @@ public: SelectorTable &Selectors; Builtin::Context &BuiltinInfo; mutable DeclarationNameTable DeclarationNames; - llvm::OwningPtr<ExternalASTSource> ExternalSource; + OwningPtr<ExternalASTSource> ExternalSource; ASTMutationListener *Listener; clang::PrintingPolicy getPrintingPolicy() const { return PrintingPolicy; } @@ -394,7 +411,7 @@ public: const TargetInfo &getTargetInfo() const { return *Target; } - const LangOptions& getLangOptions() const { return LangOpts; } + const LangOptions& getLangOpts() const { return LangOpts; } DiagnosticsEngine &getDiagnostics() const; @@ -468,7 +485,7 @@ public: const FieldDecl *LastFD) const; // Access to the set of methods overridden by the given C++ method. - typedef CXXMethodVector::iterator overridden_cxx_method_iterator; + typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator; overridden_cxx_method_iterator overridden_methods_begin(const CXXMethodDecl *Method) const; @@ -482,6 +499,56 @@ public: void addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden); + /// \brief Notify the AST context that a new import declaration has been + /// parsed or implicitly created within this translation unit. + void addedLocalImportDecl(ImportDecl *Import); + + static ImportDecl *getNextLocalImport(ImportDecl *Import) { + return Import->NextLocalImport; + } + + /// \brief Iterator that visits import declarations. + class import_iterator { + ImportDecl *Import; + + public: + typedef ImportDecl *value_type; + typedef ImportDecl *reference; + typedef ImportDecl *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + import_iterator() : Import() { } + explicit import_iterator(ImportDecl *Import) : Import(Import) { } + + reference operator*() const { return Import; } + pointer operator->() const { return Import; } + + import_iterator &operator++() { + Import = ASTContext::getNextLocalImport(Import); + return *this; + } + + import_iterator operator++(int) { + import_iterator Other(*this); + ++(*this); + return Other; + } + + friend bool operator==(import_iterator X, import_iterator Y) { + return X.Import == Y.Import; + } + + friend bool operator!=(import_iterator X, import_iterator Y) { + return X.Import != Y.Import; + } + }; + + import_iterator local_import_begin() const { + return import_iterator(FirstLocalImport); + } + import_iterator local_import_end() const { return import_iterator(); } + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } @@ -500,7 +567,9 @@ public: CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; + CanQualType PseudoObjectTy, ARCUnbridgedCastTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; + CanQualType ObjCBuiltinBoolTy; // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -519,7 +588,7 @@ public: /// The external AST source provides the ability to load parts of /// the abstract syntax tree as needed from some external storage, /// e.g., a precompiled header. - void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source); + void setExternalSource(OwningPtr<ExternalASTSource> &Source); /// \brief Retrieve a pointer to the external AST source associated /// with this AST context, if any. @@ -800,7 +869,8 @@ public: QualType getPackExpansionType(QualType Pattern, llvm::Optional<unsigned> NumExpansions); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const; + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + ObjCInterfaceDecl *PrevDecl = 0) const; QualType getObjCObjectType(QualType Base, ObjCProtocolDecl * const *Protocols, @@ -815,7 +885,7 @@ public: QualType getTypeOfType(QualType t) const; /// getDecltypeType - C++0x decltype. - QualType getDecltypeType(Expr *e) const; + QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; /// getUnaryTransformType - unary type transforms QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType, @@ -838,6 +908,14 @@ public: /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4). CanQualType getSizeType() const; + /// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5), + /// defined in <stdint.h>. + CanQualType getIntMaxType() const; + + /// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5), + /// defined in <stdint.h>. + CanQualType getUIntMaxType() const; + /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this /// returns a type compatible with the type defined in <stddef.h> as defined /// by the target. @@ -851,7 +929,7 @@ public: /// Used when in C++, as a GCC extension. QualType getUnsignedWCharType() const; - /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?) + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; @@ -874,6 +952,14 @@ public: return ObjCConstantStringType; } + QualType getObjCNSStringType() const { + return ObjCNSStringType; + } + + void setObjCNSStringType(QualType T) { + ObjCNSStringType = T; + } + /// \brief Retrieve the type that 'id' has been defined to, which may be /// different from the built-in 'id' if 'id' has been typedef'd. QualType getObjCIdRedefinitionType() const { @@ -972,7 +1058,7 @@ public: /// \brief The result type of logical operations, '<', '>', '!=', etc. QualType getLogicalOperationType() const { - return getLangOptions().CPlusPlus ? BoolTy : IntTy; + return getLangOpts().CPlusPlus ? BoolTy : IntTy; } /// getObjCEncodingForType - Emit the ObjC type encoding for the @@ -999,7 +1085,8 @@ public: /// /// \returns true if an error occurred (e.g., because one of the parameter /// types is incomplete), false otherwise. - bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S) + bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S, + bool Extended = false) const; /// getObjCEncodingForBlock - Return the encoded type for this block @@ -1041,9 +1128,6 @@ public: return getTypeDeclType(getObjCSelDecl()); } - void setObjCProtoType(QualType QT); - QualType getObjCProtoType() const { return ObjCProtoType; } - /// \brief Retrieve the typedef declaration corresponding to the predefined /// Objective-C 'Class' type. TypedefDecl *getObjCClassDecl() const; @@ -1055,6 +1139,15 @@ public: return getTypeDeclType(getObjCClassDecl()); } + /// \brief Retrieve the Objective-C class declaration corresponding to + /// the predefined 'Protocol' class. + ObjCInterfaceDecl *getObjCProtocolDecl() const; + + /// \brief Retrieve the type of the Objective-C "Protocol" class. + QualType getObjCProtoType() const { + return getObjCInterfaceType(getObjCProtocolDecl()); + } + void setBuiltinVaListType(QualType T); QualType getBuiltinVaListType() const { return BuiltinVaListType; } @@ -1064,6 +1157,11 @@ public: return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); } + /// getQualifiedType - Un-split a SplitQualType. + QualType getQualifiedType(SplitQualType split) const { + return getQualifiedType(split.Ty, split.Quals); + } + /// getQualifiedType - Returns a type with additional qualifiers. QualType getQualifiedType(QualType T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) @@ -1127,6 +1225,7 @@ public: private: CanQualType getFromTargetType(unsigned Type) const; + std::pair<uint64_t, unsigned> getTypeInfoImpl(const Type *T) const; //===--------------------------------------------------------------------===// // Type Predicates. @@ -1230,7 +1329,8 @@ public: const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const; - void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS) const; + void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, + bool Simple = false) const; /// getASTObjCImplementationLayout - Get or compute information about /// the layout of the specified Objective-C implementation. This may @@ -1246,6 +1346,9 @@ public: /// of class definition. const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits. + uint64_t getFieldOffset(const ValueDecl *FD) const; + bool isNearlyEmpty(const CXXRecordDecl *RD) const; MangleContext *createMangleContext(); @@ -1282,7 +1385,7 @@ public: CanQualType getCanonicalParamType(QualType T) const; /// \brief Determine whether the given types are equivalent. - bool hasSameType(QualType T1, QualType T2) { + bool hasSameType(QualType T1, QualType T2) const { return getCanonicalType(T1) == getCanonicalType(T2); } @@ -1302,7 +1405,7 @@ public: /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. - bool hasSameUnqualifiedType(QualType T1, QualType T2) { + bool hasSameUnqualifiedType(QualType T1, QualType T2) const { return getCanonicalType(T1).getTypePtr() == getCanonicalType(T2).getTypePtr(); } @@ -1590,6 +1693,8 @@ public: return Res; } + bool isSentinelNullExpr(const Expr *E); + /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists. ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D); /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. @@ -1622,6 +1727,11 @@ public: const ObjCMethodDecl *Redecl) { ObjCMethodRedecls[MD] = Redecl; } + + /// \brief Returns the objc interface that \arg ND belongs to if it is a + /// objc method/property/ivar etc. that is part of an interface, + /// otherwise returns null. + ObjCInterfaceDecl *getObjContainingInterface(NamedDecl *ND) const; /// \brief Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); @@ -1671,6 +1781,8 @@ public: /// it is not used. bool DeclMustBeEmitted(const Decl *D); + /// \brief Retrieve the lambda mangling number for a lambda expression. + unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator); /// \brief Used by ParmVarDecl to store on the side the /// index of the parameter when it exceeds the size of the normal bitfield. @@ -1751,13 +1863,20 @@ private: const FieldDecl *Field, bool OutermostType = false, bool EncodingProperty = false, - bool StructField = false) const; + bool StructField = false, + bool EncodeBlockParameters = false, + bool EncodeClassNames = false) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, const FieldDecl *Field, bool includeVBases = true) const; - + + // Adds the encoding of a method parameter or return type. + void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, + QualType T, std::string& S, + bool Extended) const; + const ASTRecordLayout & getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const; @@ -1795,13 +1914,19 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { } // end namespace clang // operator new and delete aren't allowed inside namespaces. -// The throw specifications are mandated by the standard. + /// @brief Placement new for using the ASTContext's allocator. /// /// This placement form of operator new uses the ASTContext's allocator for -/// obtaining memory. It is a non-throwing new, which means that it returns -/// null on error. (If that is what the allocator does. The current does, so if -/// this ever changes, this operator will have to be changed, too.) +/// obtaining memory. +/// +/// IMPORTANT: These are also declared in clang/AST/Attr.h! Any changes here +/// need to also be made there. +/// +/// We intentionally avoid using a nothrow specification here so that the calls +/// to this operator will not perform a null check on the result -- the +/// underlying allocator never returns null pointers. +/// /// Usage looks like this (assuming there's an ASTContext 'Context' in scope): /// @code /// // Default alignment (8) @@ -1819,7 +1944,7 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { /// allocator supports it). /// @return The allocated memory. Could be NULL. inline void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment) throw () { + size_t Alignment) { return C.Allocate(Bytes, Alignment); } /// @brief Placement delete companion to the new above. @@ -1828,14 +1953,17 @@ inline void *operator new(size_t Bytes, const clang::ASTContext &C, /// invoking it directly; see the new operator for more details. This operator /// is called implicitly by the compiler if a placement new expression using /// the ASTContext throws in the object constructor. -inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) - throw () { +inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { C.Deallocate(Ptr); } /// This placement form of operator new[] uses the ASTContext's allocator for -/// obtaining memory. It is a non-throwing new[], which means that it returns -/// null on error. +/// obtaining memory. +/// +/// We intentionally avoid using a nothrow specification here so that the calls +/// to this operator will not perform a null check on the result -- the +/// underlying allocator never returns null pointers. +/// /// Usage looks like this (assuming there's an ASTContext 'Context' in scope): /// @code /// // Default alignment (8) @@ -1853,7 +1981,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) /// allocator supports it). /// @return The allocated memory. Could be NULL. inline void *operator new[](size_t Bytes, const clang::ASTContext& C, - size_t Alignment = 8) throw () { + size_t Alignment = 8) { return C.Allocate(Bytes, Alignment); } @@ -1863,8 +1991,7 @@ inline void *operator new[](size_t Bytes, const clang::ASTContext& C, /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the ASTContext throws in the object constructor. -inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) - throw () { +inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) { C.Deallocate(Ptr); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h index b005711..64e955e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG @@ -44,7 +44,7 @@ namespace clang { unsigned NumPrevArgs, SmallVectorImpl<char> &Output, void *Cookie, - SmallVectorImpl<intptr_t> &QualTypeVals); + ArrayRef<intptr_t> QualTypeVals); } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h index b583fbf..7157efe 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h @@ -255,6 +255,12 @@ namespace clang { /// \brief Return the set of declarations that we know are not equivalent. NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } + + /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. + /// Mark the Decl as complete, filling it in as much as possible. + /// + /// \param D A declaration in the "to" context. + virtual void CompleteDecl(Decl* D); /// \brief Note that we have imported the "from" declaration by mapping it /// to the (potentially-newly-created) "to" declaration. diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h index 793d3ee..cb038a0 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h @@ -24,6 +24,8 @@ namespace clang { class FunctionTemplateDecl; class ObjCCategoryDecl; class ObjCInterfaceDecl; + class ObjCContainerDecl; + class ObjCPropertyDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -60,6 +62,21 @@ public: /// \brief A new objc category class was added for an interface. virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) {} + + /// \brief A objc class extension redeclared or introduced a property. + /// + /// \param Prop the property in the class extension + /// + /// \param OrigProp the property from the original interface that was declared + /// or null if the property was introduced. + /// + /// \param ClassExt the class extension. + virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt) {} + + // NOTE: If new methods are added they should also be added to + // MultiplexASTMutationListener. }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h index cf2e3c5..ef1aa25 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Attr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h @@ -23,6 +23,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstring> #include <algorithm> @@ -39,19 +40,17 @@ namespace clang { // Defined in ASTContext.h void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment = 16) throw (); + size_t Alignment = 16); // FIXME: Being forced to not have a default argument here due to redeclaration // rules on default arguments sucks void *operator new[](size_t Bytes, const clang::ASTContext &C, - size_t Alignment) throw (); + size_t Alignment); // It is good practice to pair new/delete operators. Also, MSVC gives many // warnings if a matching delete overload is not declared, even though the // throw() spec guarantees it will not be implicitly called. -void operator delete(void *Ptr, const clang::ASTContext &C, size_t) - throw (); -void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) - throw (); +void operator delete(void *Ptr, const clang::ASTContext &C, size_t); +void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); namespace clang { @@ -103,11 +102,17 @@ public: // Clone this attribute. virtual Attr* clone(ASTContext &C) const = 0; + virtual bool isLateParsed() const { return false; } + + // Pretty print this attribute. + virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0; + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *) { return true; } }; class InheritableAttr : public Attr { + virtual void anchor(); protected: InheritableAttr(attr::Kind AK, SourceRange R) : Attr(AK, R) {} @@ -123,6 +128,7 @@ public: }; class InheritableParamAttr : public InheritableAttr { + virtual void anchor(); protected: InheritableParamAttr(attr::Kind AK, SourceRange R) : InheritableAttr(AK, R) {} diff --git a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def new file mode 100644 index 0000000..34e6fc5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def @@ -0,0 +1,224 @@ +//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the database about various builtin singleton types. +// +// BuiltinType::Id is the enumerator defining the type. +// +// Context.SingletonId is the global singleton of this type. Some global +// singletons are shared by multiple types. +// +// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been +// covered by any other #define. Defining this macro covers all +// the builtins. +// +// SIGNED_TYPE(Id, SingletonId) - A signed integral type. +// +// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type. +// +// FLOATING_TYPE(Id, SingletonId) - A floating-point type. +// +// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder +// types are used to perform context-sensitive checking of specific +// forms of expression. +// +// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds +// to a builtin which uses a shared singleton type. +// +//===----------------------------------------------------------------------===// + +#ifndef SIGNED_TYPE +#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef UNSIGNED_TYPE +#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef FLOATING_TYPE +#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef PLACEHOLDER_TYPE +#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef SHARED_SINGLETON_TYPE +#define SHARED_SINGLETON_TYPE(Expansion) Expansion +#endif + +//===- Builtin Types ------------------------------------------------------===// + +// void +BUILTIN_TYPE(Void, VoidTy) + +//===- Unsigned Types -----------------------------------------------------===// + +// 'bool' in C++, '_Bool' in C99 +UNSIGNED_TYPE(Bool, BoolTy) + +// 'char' for targets where it's unsigned +SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy)) + +// 'unsigned char', explicitly qualified +UNSIGNED_TYPE(UChar, UnsignedCharTy) + +// 'wchar_t' for targets where it's unsigned +SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) + +// 'char16_t' in C++ +UNSIGNED_TYPE(Char16, Char16Ty) + +// 'char32_t' in C++ +UNSIGNED_TYPE(Char32, Char32Ty) + +// 'unsigned short' +UNSIGNED_TYPE(UShort, UnsignedShortTy) + +// 'unsigned int' +UNSIGNED_TYPE(UInt, UnsignedIntTy) + +// 'unsigned long' +UNSIGNED_TYPE(ULong, UnsignedLongTy) + +// 'unsigned long long' +UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy) + +// '__uint128_t' +UNSIGNED_TYPE(UInt128, UnsignedInt128Ty) + +//===- Signed Types -------------------------------------------------------===// + +// 'char' for targets where it's signed +SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy)) + +// 'signed char', explicitly qualified +SIGNED_TYPE(SChar, SignedCharTy) + +// 'wchar_t' for targets where it's signed +SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy)) + +// 'short' or 'signed short' +SIGNED_TYPE(Short, ShortTy) + +// 'int' or 'signed int' +SIGNED_TYPE(Int, IntTy) + +// 'long' or 'signed long' +SIGNED_TYPE(Long, LongTy) + +// 'long long' or 'signed long long' +SIGNED_TYPE(LongLong, LongLongTy) + +// '__int128_t' +SIGNED_TYPE(Int128, Int128Ty) + +//===- Floating point types -----------------------------------------------===// + +// 'half' in OpenCL, '__fp16' in ARM NEON. +FLOATING_TYPE(Half, HalfTy) + +// 'float' +FLOATING_TYPE(Float, FloatTy) + +// 'double' +FLOATING_TYPE(Double, DoubleTy) + +// 'long double' +FLOATING_TYPE(LongDouble, LongDoubleTy) + +//===- Language-specific types --------------------------------------------===// + +// This is the type of C++0x 'nullptr'. +BUILTIN_TYPE(NullPtr, NullPtrTy) + +// The primitive Objective C 'id' type. The user-visible 'id' +// type is a typedef of an ObjCObjectPointerType to an +// ObjCObjectType with this as its base. In fact, this only ever +// shows up in an AST as the base type of an ObjCObjectType. +BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy) + +// The primitive Objective C 'Class' type. The user-visible +// 'Class' type is a typedef of an ObjCObjectPointerType to an +// ObjCObjectType with this as its base. In fact, this only ever +// shows up in an AST as the base type of an ObjCObjectType. +BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy) + +// The primitive Objective C 'SEL' type. The user-visible 'SEL' +// type is a typedef of a PointerType to this. +BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy) + +// This represents the type of an expression whose type is +// totally unknown, e.g. 'T::foo'. It is permitted for this to +// appear in situations where the structure of the type is +// theoretically deducible. +BUILTIN_TYPE(Dependent, DependentTy) + +// The type of an unresolved overload set. A placeholder type. +// Expressions with this type have one of the following basic +// forms, with parentheses generally permitted: +// foo # possibly qualified, not if an implicit access +// foo # possibly qualified, not if an implicit access +// &foo # possibly qualified, not if an implicit access +// x->foo # only if might be a static member function +// &x->foo # only if might be a static member function +// &Class::foo # when a pointer-to-member; sub-expr also has this type +// OverloadExpr::find can be used to analyze the expression. +// +// Overload should be the first placeholder type, or else change +// BuiltinType::isNonOverloadPlaceholderType() +PLACEHOLDER_TYPE(Overload, OverloadTy) + +// The type of a bound C++ non-static member function. +// A placeholder type. Expressions with this type have one of the +// following basic forms: +// foo # if an implicit access +// x->foo # if only contains non-static members +PLACEHOLDER_TYPE(BoundMember, BoundMemberTy) + +// The type of an expression which refers to a pseudo-object, +// such as those introduced by Objective C's @property or +// VS.NET's __property declarations. A placeholder type. The +// pseudo-object is actually accessed by emitting a call to +// some sort of function or method; typically there is a pair +// of a setter and a getter, with the setter used if the +// pseudo-object reference is used syntactically as the +// left-hand-side of an assignment operator. +// +// A pseudo-object reference naming an Objective-C @property is +// always a dot access with a base of object-pointer type, +// e.g. 'x.foo'. +// +// In VS.NET, a __property declaration creates an implicit +// member with an associated name, which can then be named +// in any of the normal ways an ordinary member could be. +PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy) + +// __builtin_any_type. A placeholder type. Useful for clients +// like debuggers that don't know what type to give something. +// Only a small number of operations are valid on expressions of +// unknown type, most notably explicit casts. +PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy) + +// The type of a cast which, in ARC, would normally require a +// __bridge, but which might be okay depending on the immediate +// context. +PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy) + +#ifdef LAST_BUILTIN_TYPE +LAST_BUILTIN_TYPE(ARCUnbridgedCast) +#undef LAST_BUILTIN_TYPE +#endif + +#undef SHARED_SINGLETON_TYPE +#undef PLACEHOLDER_TYPE +#undef FLOATING_TYPE +#undef SIGNED_TYPE +#undef UNSIGNED_TYPE +#undef BUILTIN_TYPE diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h index 38e6b41..6cce888 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h @@ -108,6 +108,8 @@ public: /// or a derived class thereof, a NULL canonical type. template<typename U> CanProxy<U> getAs() const; + template<typename U> CanProxy<U> castAs() const; + /// \brief Overloaded arrow operator that produces a canonical type /// proxy. CanProxy<T> operator->() const; @@ -753,6 +755,13 @@ CanProxy<U> CanQual<T>::getAs() const { } template<typename T> +template<typename U> +CanProxy<U> CanQual<T>::castAs() const { + assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); + return CanQual<U>::CreateUnsafe(Stored); +} + +template<typename T> CanProxy<T> CanQual<T>::operator->() const { return CanProxy<T>(*this); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h index a02a2ce..11696db 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h @@ -22,6 +22,7 @@ #include "clang/Basic/Linkage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/Support/Compiler.h" namespace clang { class CXXTemporary; @@ -40,7 +41,8 @@ class DependentFunctionTemplateSpecializationInfo; class TypeLoc; class UnresolvedSetImpl; class LabelStmt; - +class Module; + /// \brief A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: @@ -66,6 +68,7 @@ public: /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { + virtual void anchor(); ASTContext &Ctx; /// The (most recently entered) anonymous namespace for this @@ -98,11 +101,15 @@ public: /// NamedDecl - This represents a decl with a name. Many decls have names such /// as ObjCMethodDecl, but not @class, etc. class NamedDecl : public Decl { + virtual void anchor(); /// Name - The name of this declaration, which is typically a normal /// identifier but may also be a special kind of name (C++ /// constructor, Objective-C selector, etc.) DeclarationName Name; +private: + NamedDecl *getUnderlyingDeclImpl(); + protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) : Decl(DK, DC, L), Name(N) { } @@ -182,15 +189,11 @@ public: /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; - /// \brief Whether this declaration was marked as being private to the - /// module in which it was defined. - bool isModulePrivate() const { return ModulePrivate; } + using Decl::isModulePrivate; + using Decl::setModulePrivate; - /// \brief Specify whether this declaration was marked as being private - /// to the module in which it was defined. - void setModulePrivate(bool MP = true) { - ModulePrivate = MP; - } + /// \brief Determine whether this declaration is hidden from name lookup. + bool isHidden() const { return Hidden; } /// \brief Determine whether this declaration is a C++ class member. bool isCXXClassMember() const { @@ -206,8 +209,8 @@ public: return DC->isRecord(); } - /// \brief Given that this declaration is a C++ class member, - /// determine whether it's an instance member of its class. + /// \brief Determine whether the given declaration is an instance member of + /// a C++ class. bool isCXXInstanceMember() const; class LinkageInfo { @@ -249,26 +252,52 @@ public: setLinkage(minLinkage(linkage(), L)); } void mergeLinkage(LinkageInfo Other) { - setLinkage(minLinkage(linkage(), Other.linkage())); + mergeLinkage(Other.linkage()); } - void mergeVisibility(Visibility V) { - setVisibility(minVisibility(visibility(), V)); - } - void mergeVisibility(Visibility V, bool E) { + // Merge the visibility V giving preference to explicit ones. + // This is used, for example, when merging the visibility of a class + // down to one of its members. If the member has no explicit visibility, + // the class visibility wins. + void mergeVisibility(Visibility V, bool E = false) { + // If one has explicit visibility and the other doesn't, keep the + // explicit one. + if (visibilityExplicit() && !E) + return; + if (!visibilityExplicit() && E) + setVisibility(V, E); + + // If both are explicit or both are implicit, keep the minimum. setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E); } + // Merge the visibility V, keeping the most restrictive one. + // This is used for cases like merging the visibility of a template + // argument to an instantiation. If we already have a hidden class, + // no argument should give it default visibility. + void mergeVisibilityWithMin(Visibility V, bool E = false) { + // Never increase the visibility + if (visibility() < V) + return; + + // If this visibility is explicit, keep it. + if (visibilityExplicit() && !E) + return; + setVisibility(V, E); + } void mergeVisibility(LinkageInfo Other) { mergeVisibility(Other.visibility(), Other.visibilityExplicit()); } + void mergeVisibilityWithMin(LinkageInfo Other) { + mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit()); + } void merge(LinkageInfo Other) { mergeLinkage(Other); mergeVisibility(Other); } - void merge(std::pair<Linkage,Visibility> LV) { - mergeLinkage(LV.first); - mergeVisibility(LV.second); + void mergeWithMin(LinkageInfo Other) { + mergeLinkage(Other); + mergeVisibilityWithMin(Other); } friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) { @@ -281,7 +310,9 @@ public: Linkage getLinkage() const; /// \brief Determines the visibility of this entity. - Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); } + Visibility getVisibility() const { + return getLinkageAndVisibility().visibility(); + } /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; @@ -291,12 +322,19 @@ public: llvm::Optional<Visibility> getExplicitVisibility() const; /// \brief Clear the linkage cache in response to a change - /// to the declaration. + /// to the declaration. void ClearLinkageCache(); /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. - NamedDecl *getUnderlyingDecl(); + NamedDecl *getUnderlyingDecl() { + // Fast-path the common case. + if (this->getKind() != UsingShadow && + this->getKind() != ObjCCompatibleAlias) + return this; + + return getUnderlyingDeclImpl(); + } const NamedDecl *getUnderlyingDecl() const { return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); } @@ -317,6 +355,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { /// location of the statement. For GNU local labels (__label__), the decl /// location is where the __label__ is. class LabelDecl : public NamedDecl { + virtual void anchor(); LabelStmt *TheStmt; /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, @@ -333,14 +372,15 @@ public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, SourceLocation GnuLabelL); - + static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID); + LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } bool isGnuLocal() const { return LocStart != getLocation(); } void setLocStart(SourceLocation L) { LocStart = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LocStart, getLocation()); } @@ -349,10 +389,12 @@ public: static bool classof(const LabelDecl *D) { return true; } static bool classofKind(Kind K) { return K == Label; } }; - + /// NamespaceDecl - Represent a C++ namespace. -class NamespaceDecl : public NamedDecl, public DeclContext { - bool IsInline : 1; +class NamespaceDecl : public NamedDecl, public DeclContext, + public Redeclarable<NamespaceDecl> +{ + virtual void anchor(); /// LocStart - The starting location of the source range, pointing /// to either the namespace or the inline keyword. @@ -360,41 +402,40 @@ class NamespaceDecl : public NamedDecl, public DeclContext { /// RBraceLoc - The ending location of the source range. SourceLocation RBraceLoc; - // For extended namespace definitions: - // - // namespace A { int x; } - // namespace A { int y; } - // - // there will be one NamespaceDecl for each declaration. - // NextNamespace points to the next extended declaration. - // OrigNamespace points to the original namespace declaration. - // OrigNamespace of the first namespace decl points to its anonymous namespace - LazyDeclPtr NextNamespace; - - /// \brief A pointer to either the original namespace definition for - /// this namespace (if the boolean value is false) or the anonymous - /// namespace that lives just inside this namespace (if the boolean - /// value is true). - /// - /// We can combine these two notions because the anonymous namespace - /// must only be stored in one of the namespace declarations (so all - /// of the namespace declarations can find it). We therefore choose - /// the original namespace declaration, since all of the namespace - /// declarations have a link directly to it; the original namespace - /// declaration itself only needs to know that it is the original - /// namespace declaration (which the boolean indicates). - llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace; - - NamespaceDecl(DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - IsInline(false), LocStart(StartLoc), RBraceLoc(), - NextNamespace(), OrigOrAnonNamespace(0, true) { } + /// \brief A pointer to either the anonymous namespace that lives just inside + /// this namespace or to the first namespace in the chain (the latter case + /// only when this is not the first in the chain), along with a + /// boolean value indicating whether this is an inline namespace. + llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline; + NamespaceDecl(DeclContext *DC, bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl); + + typedef Redeclarable<NamespaceDecl> redeclarable_base; + virtual NamespaceDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual NamespaceDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual NamespaceDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id); + bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl); + + static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -411,67 +452,60 @@ public: /// \brief Returns true if this is an inline namespace declaration. bool isInline() const { - return IsInline; + return AnonOrFirstNamespaceAndInline.getInt(); } /// \brief Set whether this is an inline namespace declaration. void setInline(bool Inline) { - IsInline = Inline; + AnonOrFirstNamespaceAndInline.setInt(Inline); } - /// \brief Return the next extended namespace declaration or null if there - /// is none. - NamespaceDecl *getNextNamespace(); - const NamespaceDecl *getNextNamespace() const { - return const_cast<NamespaceDecl *>(this)->getNextNamespace(); - } + /// \brief Get the original (first) namespace declaration. + NamespaceDecl *getOriginalNamespace() { + if (isFirstDeclaration()) + return this; - /// \brief Set the next extended namespace declaration. - void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + return AnonOrFirstNamespaceAndInline.getPointer(); + } /// \brief Get the original (first) namespace declaration. - NamespaceDecl *getOriginalNamespace() const { - if (OrigOrAnonNamespace.getInt()) - return const_cast<NamespaceDecl *>(this); + const NamespaceDecl *getOriginalNamespace() const { + if (isFirstDeclaration()) + return this; - return OrigOrAnonNamespace.getPointer(); + return AnonOrFirstNamespaceAndInline.getPointer(); } /// \brief Return true if this declaration is an original (first) declaration /// of the namespace. This is false for non-original (subsequent) namespace /// declarations and anonymous namespaces. bool isOriginalNamespace() const { - return getOriginalNamespace() == this; - } - - /// \brief Set the original (first) namespace declaration. - void setOriginalNamespace(NamespaceDecl *ND) { - if (ND != this) { - OrigOrAnonNamespace.setPointer(ND); - OrigOrAnonNamespace.setInt(false); - } + return isFirstDeclaration(); } + /// \brief Retrieve the anonymous namespace nested inside this namespace, + /// if any. NamespaceDecl *getAnonymousNamespace() const { - return getOriginalNamespace()->OrigOrAnonNamespace.getPointer(); + return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer(); } void setAnonymousNamespace(NamespaceDecl *D) { - assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent()->getRedeclContext() == this); - getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); + getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D); } - virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } - const NamespaceDecl *getCanonicalDecl() const { - return getOriginalNamespace(); + /// Retrieves the canonical declaration of this namespace. + NamespaceDecl *getCanonicalDecl() { + return getOriginalNamespace(); } - - virtual SourceRange getSourceRange() const { + const NamespaceDecl *getCanonicalDecl() const { + return getOriginalNamespace(); + } + + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LocStart, RBraceLoc); } - SourceLocation getLocStart() const { return LocStart; } + SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } SourceLocation getRBraceLoc() const { return RBraceLoc; } void setLocStart(SourceLocation L) { LocStart = L; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -486,7 +520,7 @@ public: static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -495,6 +529,7 @@ public: /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. class ValueDecl : public NamedDecl { + virtual void anchor(); QualType DeclType; protected: @@ -505,6 +540,12 @@ public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } + /// \brief Determine whether this symbol is weakly-imported, + /// or declared with the weak or weak-ref attr. + bool isWeak() const { + return hasAttr<WeakAttr>() || hasAttr<WeakRefAttr>() || isWeakImported(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ValueDecl *D) { return true; } @@ -537,7 +578,7 @@ struct QualifierInfo { void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, TemplateParameterList **TPLists); - + private: // Copy constructor and copy assignment are disabled. QualifierInfo(const QualifierInfo&); @@ -592,7 +633,10 @@ public: /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY { + return getOuterLocStart(); + } /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -600,15 +644,15 @@ public: return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : 0; } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { return hasExtInfo() ? getExtInfo()->QualifierLoc : NestedNameSpecifierLoc(); } - + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { @@ -655,8 +699,9 @@ struct EvaluatedStmt { /// integral constant expression. bool CheckingICE : 1; - /// \brief Whether this statement is an integral constant - /// expression. Only valid if CheckedICE is true. + /// \brief Whether this statement is an integral constant expression, + /// or in C++11, whether the statement is a constant expression. Only + /// valid if CheckedICE is true. bool IsICE : 1; Stmt *Value; @@ -675,6 +720,13 @@ public: /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); + /// \brief Initialization styles. + enum InitializationStyle { + CInit, ///< C-style initialization with assignment + CallInit, ///< Call-style initialization (C++98) + ListInit ///< Direct list-initialization (C++11) + }; + protected: /// \brief Placeholder type used in Init to denote an unparsed C++ default /// argument. @@ -700,14 +752,15 @@ private: unsigned SClass : 3; unsigned SClassAsWritten : 3; unsigned ThreadSpecified : 1; - unsigned HasCXXDirectInit : 1; + unsigned InitStyle : 2; /// \brief Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. unsigned ExceptionVar : 1; - + /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization (NRVO). + /// slot of its function, enabling the named return value optimization + /// (NRVO). unsigned NRVOVariable : 1; /// \brief Whether this variable is the for-range-declaration in a C++0x @@ -721,14 +774,14 @@ private: /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; }; - enum { NumVarDeclBits = 13 }; + enum { NumVarDeclBits = 14 }; friend class ASTDeclReader; friend class StmtIteratorBase; - + protected: enum { NumParameterIndexBits = 8 }; - + class ParmVarDeclBitfields { friend class ParmVarDecl; friend class ASTDeclReader; @@ -749,7 +802,7 @@ protected: /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was /// declared. - unsigned ScopeDepthOrObjCQuals : 8; + unsigned ScopeDepthOrObjCQuals : 7; /// The number of parameters preceding this parameter in the /// function parameter scope in which it was declared. @@ -777,22 +830,28 @@ protected: typedef Redeclarable<VarDecl> redeclarable_base; virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual VarDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual VarDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten); - virtual SourceRange getSourceRange() const; + static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + virtual SourceRange getSourceRange() const LLVM_READONLY; StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; @@ -823,12 +882,12 @@ public: return getStorageClass() >= SC_Auto; } - /// isStaticLocal - Returns true if a variable with function scope is a + /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { return getStorageClass() == SC_Static && !isFileVarDecl(); } - + /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { @@ -896,11 +955,17 @@ public: /// \brief Check whether this declaration is a definition. If this could be /// a tentative definition (in C), don't check whether there's an overriding /// definition. - DefinitionKind isThisDeclarationADefinition() const; + DefinitionKind isThisDeclarationADefinition(ASTContext &) const; + DefinitionKind isThisDeclarationADefinition() const { + return isThisDeclarationADefinition(getASTContext()); + } /// \brief Check whether this variable is defined in this /// translation unit. - DefinitionKind hasDefinition() const; + DefinitionKind hasDefinition(ASTContext &) const; + DefinitionKind hasDefinition() const { + return hasDefinition(getASTContext()); + } /// \brief Get the tentative definition that acts as the real definition in /// a TU. Returns null if there is a proper definition available. @@ -914,26 +979,32 @@ public: bool isTentativeDefinitionNow() const; /// \brief Get the real (not just tentative) definition for this declaration. - VarDecl *getDefinition(); + VarDecl *getDefinition(ASTContext &); + const VarDecl *getDefinition(ASTContext &C) const { + return const_cast<VarDecl*>(this)->getDefinition(C); + } + VarDecl *getDefinition() { + return getDefinition(getASTContext()); + } const VarDecl *getDefinition() const { return const_cast<VarDecl*>(this)->getDefinition(); } - /// \brief Determine whether this is or was instantiated from an out-of-line + /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. virtual bool isOutOfLine() const; /// \brief If this is a static data member, find its out-of-line definition. VarDecl *getOutOfLineDefinition(); - + /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; - + if (getDeclContext()->getRedeclContext()->isFileContext()) return true; - + if (isStaticDataMember()) return true; @@ -996,7 +1067,7 @@ public: void setInit(Expr *I); /// \brief Determine whether this variable is a reference that - /// extends the lifetime of its temporary initializer. + /// extends the lifetime of its temporary initializer. /// /// A reference extends the lifetime of its temporary initializer if /// it's initializer is an rvalue that would normally go out of scope @@ -1009,41 +1080,21 @@ public: /// \endcode bool extendsLifetimeOfTemporary() const; - EvaluatedStmt *EnsureEvaluatedStmt() const { - EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); - if (!Eval) { - Stmt *S = Init.get<Stmt *>(); - Eval = new (getASTContext()) EvaluatedStmt; - Eval->Value = S; - Init = Eval; - } - return Eval; - } - - /// \brief Check whether we are in the process of checking whether the - /// initializer can be evaluated. - bool isEvaluatingValue() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - return Eval->IsEvaluating; - - return false; - } + /// \brief Determine whether this variable's value can be used in a + /// constant expression, according to the relevant language standard. + /// This only checks properties of the declaration, and does not check + /// whether the initializer is in fact a constant expression. + bool isUsableInConstantExpressions(ASTContext &C) const; - /// \brief Note that we now are checking whether the initializer can be - /// evaluated. - void setEvaluatingValue() const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->IsEvaluating = true; - } + EvaluatedStmt *ensureEvaluatedStmt() const; - /// \brief Note that constant evaluation has computed the given - /// value for this variable's initializer. - void setEvaluatedValue(const APValue &Value) const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->IsEvaluating = false; - Eval->WasEvaluated = true; - Eval->Evaluated = Value; - } + /// \brief Attempt to evaluate the value of the initializer attached to this + /// declaration, and produce notes explaining why it cannot be evaluated or is + /// not a constant expression. Returns a pointer to the value if evaluation + /// succeeded, 0 otherwise. + APValue *evaluateValue() const; + APValue *evaluateValue( + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const; /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer @@ -1065,8 +1116,9 @@ public: return false; } - /// \brief Determines whether the initializer is an integral - /// constant expression. + /// \brief Determines whether the initializer is an integral constant + /// expression, or in C++11, whether the initializer is a constant + /// expression. /// /// \pre isInitKnownICE() bool isInitICE() const { @@ -1075,41 +1127,31 @@ public: return Init.get<EvaluatedStmt *>()->IsICE; } - /// \brief Check whether we are in the process of checking the initializer - /// is an integral constant expression. - bool isCheckingICE() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - return Eval->CheckingICE; - - return false; - } + /// \brief Determine whether the value of the initializer attached to this + /// declaration is an integral constant expression. + bool checkInitIsICE() const; - /// \brief Note that we now are checking whether the initializer is an - /// integral constant expression. - void setCheckingICE() const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->CheckingICE = true; + void setInitStyle(InitializationStyle Style) { + VarDeclBits.InitStyle = Style; } - /// \brief Note that we now know whether the initializer is an - /// integral constant expression. - void setInitKnownICE(bool IsICE) const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->CheckingICE = false; - Eval->CheckedICE = true; - Eval->IsICE = IsICE; + /// \brief The style of initialization for this declaration. + /// + /// C-style initialization is "int x = 1;". Call-style initialization is + /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be + /// the expression inside the parens or a "ClassType(a,b,c)" class constructor + /// expression for class types. List-style initialization is C++11 syntax, + /// e.g. "int x{1};". Clients can distinguish between different forms of + /// initialization by checking this value. In particular, "int x = {1};" is + /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the + /// Init expression in all three cases is an InitListExpr. + InitializationStyle getInitStyle() const { + return static_cast<InitializationStyle>(VarDeclBits.InitStyle); } - void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; } - - /// hasCXXDirectInitializer - If true, the initializer was a direct - /// initializer, e.g: "int x(1);". The Init expression will be the expression - /// inside the parens or a "ClassType(a,b,c)" class constructor expression for - /// class types. Clients can distinguish between "int x(1);" and "int x=1;" - /// by checking hasCXXDirectInitializer. - /// - bool hasCXXDirectInitializer() const { - return VarDeclBits.HasCXXDirectInit; + /// \brief Whether the initializer is a direct-initializer (list or call). + bool isDirectInit() const { + return getInitStyle() != CInit; } /// \brief Determine whether this variable is the exception variable in a @@ -1118,7 +1160,7 @@ public: return VarDeclBits.ExceptionVar; } void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } - + /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). /// @@ -1143,7 +1185,7 @@ public: /// Generally such variables are also 'const' for safety. bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } - + /// Whether this variable is (C++0x) constexpr. bool isConstexpr() const { return VarDeclBits.IsConstexpr; } void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } @@ -1153,15 +1195,15 @@ public: /// from which it was instantiated. VarDecl *getInstantiatedFromStaticDataMember() const; - /// \brief If this variable is a static data member, determine what kind of + /// \brief If this variable is a static data member, determine what kind of /// template specialization or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; - + /// \brief If this variable is an instantiation of a static data member of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - + /// \brief For a static data member that was instantiated from a static /// data member of a class template, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, @@ -1174,11 +1216,14 @@ public: }; class ImplicitParamDecl : public VarDecl { + virtual void anchor(); public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T); + static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID); + ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, @@ -1218,8 +1263,10 @@ public: StorageClass S, StorageClass SCAsWritten, Expr *DefArg); - virtual SourceRange getSourceRange() const; + static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + virtual SourceRange getSourceRange() const LLVM_READONLY; + void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; setParameterIndex(parameterIndex); @@ -1229,7 +1276,8 @@ public: assert(!ParmVarDeclBits.IsObjCMethodParam); ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; - assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!"); + assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth + && "truncation!"); setParameterIndex(parameterIndex); } @@ -1276,20 +1324,14 @@ public: const Expr *getDefaultArg() const { return const_cast<ParmVarDecl *>(this)->getDefaultArg(); } - + void setDefaultArg(Expr *defarg) { Init = reinterpret_cast<Stmt *>(defarg); } - unsigned getNumDefaultArgTemporaries() const; - CXXTemporary *getDefaultArgTemporary(unsigned i); - const CXXTemporary *getDefaultArgTemporary(unsigned i) const { - return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i); - } - /// \brief Retrieve the source range that covers the entire default /// argument. - SourceRange getDefaultArgRange() const; + SourceRange getDefaultArgRange() const; void setUninstantiatedDefaultArg(Expr *arg) { Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg); } @@ -1351,7 +1393,7 @@ public: /// \brief Determine whether this parameter is actually a function /// parameter pack. bool isParameterPack() const; - + /// setOwningFunction - Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the /// FunctionDecls that own them, this routine is required to update @@ -1362,7 +1404,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ParmVarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ParmVar; } - + private: enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; @@ -1371,7 +1413,7 @@ private: setParameterIndexLarge(parameterIndex); return; } - + ParmVarDeclBits.ParameterIndex = parameterIndex; assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); } @@ -1379,7 +1421,7 @@ private: unsigned d = ParmVarDeclBits.ParameterIndex; return d == ParameterIndexSentinel ? getParameterIndexLarge() : d; } - + void setParameterIndexLarge(unsigned parameterIndex); unsigned getParameterIndexLarge() const; }; @@ -1394,7 +1436,7 @@ private: /// FunctionDecl (e.g., the translation unit); this FunctionDecl /// contains all of the information known about the function. Other, /// previous declarations of the function are available via the -/// getPreviousDeclaration() chain. +/// getPreviousDecl() chain. class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: @@ -1415,6 +1457,11 @@ private: /// no formals. ParmVarDecl **ParamInfo; + /// DeclsInPrototypeScope - Array of pointers to NamedDecls for + /// decls defined in the function prototype that are not parameters. E.g. + /// 'enum Y' in 'void f(enum Y {AA} x) {}'. + llvm::ArrayRef<NamedDecl*> DeclsInPrototypeScope; + LazyDeclStmtPtr Body; // FIXME: This can be packed into the bitfields in Decl. @@ -1456,7 +1503,7 @@ private: /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion4<FunctionTemplateDecl *, + llvm::PointerUnion4<FunctionTemplateDecl *, MemberSpecializationInfo *, FunctionTemplateSpecializationInfo *, DependentFunctionTemplateSpecializationInfo *> @@ -1486,7 +1533,7 @@ private: /// \param TemplateArgsAsWritten location info of template arguments. /// /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. + /// specialization was first instantiated. void setFunctionTemplateSpecialization(ASTContext &C, FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, @@ -1524,15 +1571,19 @@ protected: typedef Redeclarable<FunctionDecl> redeclarable_base; virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual FunctionDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual FunctionDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, @@ -1560,6 +1611,8 @@ public: bool hasWrittenPrototype = true, bool isConstexprSpecified = false); + static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); + DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -1570,7 +1623,7 @@ public: void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1656,7 +1709,7 @@ public: void setTrivial(bool IT) { IsTrivial = IT; } /// Whether this function is defaulted per C++0x. Only valid for - /// special member functions. + /// special member functions. bool isDefaulted() const { return IsDefaulted; } void setDefaulted(bool D = true) { IsDefaulted = D; } @@ -1774,6 +1827,11 @@ public: setParams(getASTContext(), NewParamInfo); } + const llvm::ArrayRef<NamedDecl*> &getDeclsInPrototypeScope() const { + return DeclsInPrototypeScope; + } + void setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls); + /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default @@ -1783,12 +1841,12 @@ public: QualType getResultType() const { return getType()->getAs<FunctionType>()->getResultType(); } - + /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } - + StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC); @@ -1799,10 +1857,10 @@ public: /// \brief Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInlineSpecified; } - + /// Set whether the "inline" keyword was specified for this function. - void setInlineSpecified(bool I) { - IsInlineSpecified = I; + void setInlineSpecified(bool I) { + IsInlineSpecified = I; IsInline = I; } @@ -1819,7 +1877,7 @@ public: bool isInlineDefinitionExternallyVisible() const; bool doesDeclarationForceExternallyVisibleDefinition() const; - + /// isOverloadedOperator - Whether this function declaration /// represents an C++ overloaded operator, e.g., "operator+". bool isOverloadedOperator() const { @@ -1852,7 +1910,7 @@ public: /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberFunction(). FunctionDecl *getInstantiatedFromMemberFunction() const; - + /// \brief What kind of templated function this is. TemplatedKind getTemplatedKind() const; @@ -1860,7 +1918,7 @@ public: /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - + /// \brief Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, @@ -1888,7 +1946,7 @@ public: TemplateOrSpecialization = Template; } - /// \brief Determine whether this function is a function template + /// \brief Determine whether this function is a function template /// specialization. bool isFunctionTemplateSpecialization() const { return getPrimaryTemplate() != 0; @@ -1899,7 +1957,7 @@ public: FunctionDecl *getClassScopeSpecializationPattern() const; /// \brief If this function is actually a function template specialization, - /// retrieve information about this function template specialization. + /// retrieve information about this function template specialization. /// Otherwise, returns NULL. FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { return TemplateOrSpecialization. @@ -1910,7 +1968,11 @@ public: /// specialization or a member of a class template specialization that can /// be implicitly instantiated. bool isImplicitlyInstantiable() const; - + + /// \brief Determines if the given function was instantiated from a + /// function template. + bool isTemplateInstantiation() const; + /// \brief Retrieve the function declaration from which this function could /// be instantiated, if it is an instantiation (rather than a non-template /// or a specialization, for example). @@ -1958,7 +2020,7 @@ public: /// \param TemplateArgsAsWritten location info of template arguments. /// /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. + /// specialization was first instantiated. void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, @@ -1994,15 +2056,21 @@ public: /// \brief Retrieve the (first) point of instantiation of a function template /// specialization or a member of a class template specialization. /// - /// \returns the first point of instantiation, if this function was - /// instantiated from a template; otherwise, returns an invalid source + /// \returns the first point of instantiation, if this function was + /// instantiated from a template; otherwise, returns an invalid source /// location. SourceLocation getPointOfInstantiation() const; - - /// \brief Determine whether this is or was instantiated from an out-of-line + + /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. virtual bool isOutOfLine() const; - + + /// \brief Identify a memory copying or setting function. + /// If the given function is a memory copy or setting function, returns + /// the corresponding Builtin ID. If the function is not a memory function, + /// returns 0. + unsigned getMemoryFunctionKind() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionDecl *D) { return true; } @@ -2056,6 +2124,8 @@ public: TypeSourceInfo *TInfo, Expr *BW, bool Mutable, bool HasInit); + static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// getFieldIndex - Returns the index of this field within its record, /// as appropriate for passing to ASTRecordLayout::getFieldOffset. unsigned getFieldIndex() const; @@ -2108,7 +2178,8 @@ public: Expr *getInClassInitializer() const { return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0; } - /// setInClassInitializer - Set the C++0x in-class initializer for this member. + /// setInClassInitializer - Set the C++0x in-class initializer for this + /// member. void setInClassInitializer(Expr *Init); /// removeInClassInitializer - Remove the C++0x in-class initializer from this /// member. @@ -2128,7 +2199,7 @@ public: return cast<RecordDecl>(getDeclContext()); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2155,7 +2226,8 @@ public: SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V); - + static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID); + const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } const llvm::APSInt &getInitVal() const { return Val; } @@ -2163,8 +2235,8 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } - SourceRange getSourceRange() const; - + SourceRange getSourceRange() const LLVM_READONLY; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumConstantDecl *D) { return true; } @@ -2177,6 +2249,7 @@ public: /// field injected from an anonymous union/struct into the parent scope. /// IndirectFieldDecl are always implicit. class IndirectFieldDecl : public ValueDecl { + virtual void anchor(); NamedDecl **Chaining; unsigned ChainingSize; @@ -2189,6 +2262,8 @@ public: static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS); + + static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); typedef NamedDecl * const *chain_iterator; chain_iterator chain_begin() const { return Chaining; } @@ -2216,6 +2291,7 @@ public: /// TypeDecl - Represents a declaration of a type. /// class TypeDecl : public NamedDecl { + virtual void anchor(); /// TypeForDecl - This indicates the Type object that represents /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and @@ -2228,6 +2304,7 @@ class TypeDecl : public NamedDecl { friend class TagDecl; friend class TemplateTypeParmDecl; friend class TagType; + friend class ASTReader; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -2239,9 +2316,9 @@ public: const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } - SourceLocation getLocStart() const { return LocStart; } + SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } void setLocStart(SourceLocation L) { LocStart = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { if (LocStart.isValid()) return SourceRange(LocStart, getLocation()); else @@ -2257,6 +2334,7 @@ public: /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { + virtual void anchor(); /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; @@ -2270,15 +2348,19 @@ protected: virtual TypedefNameDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual TypedefNameDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual TypedefNameDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; TypeSourceInfo *getTypeSourceInfo() const { return TInfo; @@ -2318,8 +2400,9 @@ public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo); - - SourceRange getSourceRange() const; + static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2338,8 +2421,9 @@ public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo); + static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2364,15 +2448,17 @@ private: /// a definition until the definition has been fully processed. bool IsCompleteDefinition : 1; +protected: /// IsBeingDefined - True if this is currently being defined. bool IsBeingDefined : 1; +private: /// IsEmbeddedInDeclarator - True if this tag declaration is /// "embedded" (i.e., defined or declared for the very first time) /// in the syntax of a declarator. bool IsEmbeddedInDeclarator : 1; - /// /brief True if this tag is free standing, e.g. "struct foo;". + /// \brief True if this tag is free standing, e.g. "struct foo;". bool IsFreeStanding : 1; protected: @@ -2381,7 +2467,7 @@ protected: unsigned NumNegativeBits : 8; /// IsScoped - True if this tag declaration is a scoped enumeration. Only - /// possible in C++0x mode. + /// possible in C++11 mode. bool IsScoped : 1; /// IsScopedUsingClassTag - If this tag declaration is a scoped enum, /// then this is true if the scoped enum was declared using the class @@ -2390,7 +2476,7 @@ protected: bool IsScopedUsingClassTag : 1; /// IsFixed - True if this is an enumeration with fixed underlying type. Only - /// possible in C++0x mode. + /// possible in C++11 or Microsoft extensions mode. bool IsFixed : 1; private: @@ -2431,20 +2517,24 @@ protected: typedef Redeclarable<TagDecl> redeclarable_base; virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual TagDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual TagDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } /// @brief Completes the definition of this tag declaration. /// /// This is a helper function for derived classes. - void completeDefinition(); - + void completeDefinition(); + public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -2456,7 +2546,7 @@ public: /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; virtual TagDecl* getCanonicalDecl(); const TagDecl* getCanonicalDecl() const { @@ -2532,7 +2622,8 @@ public: bool isEnum() const { return getTagKind() == TTK_Enum; } TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); + return hasExtInfo() ? 0 : + TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); } void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); @@ -2543,15 +2634,15 @@ public: return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : 0; } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { return hasExtInfo() ? getExtInfo()->QualifierLoc : NestedNameSpecifierLoc(); } - + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { @@ -2580,9 +2671,11 @@ public: friend class ASTDeclWriter; }; -/// EnumDecl - Represents an enum. As an extension, we allow forward-declared -/// enums. +/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared +/// with a fixed underlying type, and in C we allow them to be forward-declared +/// with no underlying type as an extension. class EnumDecl : public TagDecl { + virtual void anchor(); /// IntegerType - This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. @@ -2606,23 +2699,16 @@ class EnumDecl : public TagDecl { /// in C++) are of the enum type instead. QualType PromotionType; - /// \brief If the enumeration was instantiated from an enumeration - /// within a class or function template, this pointer refers to the - /// enumeration declared within the template. - EnumDecl *InstantiatedFrom; - - // The number of positive and negative bits required by the - // enumerators are stored in the SubclassBits field. - enum { - NumBitsWidth = 8, - NumBitsMask = (1 << NumBitsWidth) - 1 - }; + /// \brief If this enumeration is an instantiation of a member enumeration + /// of a class template specialization, this is the member specialization + /// information. + MemberSpecializationInfo *SpecializationInfo; EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), - InstantiatedFrom(0) { + SpecializationInfo(0) { assert(Scoped || !ScopedUsingClassTag); IntegerType = (const Type*)0; NumNegativeBits = 0; @@ -2631,6 +2717,9 @@ class EnumDecl : public TagDecl { IsScopedUsingClassTag = ScopedUsingClassTag; IsFixed = Fixed; } + + void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, + TemplateSpecializationKind TSK); public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); @@ -2639,11 +2728,22 @@ public: return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } - const EnumDecl *getPreviousDeclaration() const { - return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + const EnumDecl *getPreviousDecl() const { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl()); } - EnumDecl *getPreviousDeclaration() { - return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + EnumDecl *getPreviousDecl() { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl()); + } + + const EnumDecl *getMostRecentDecl() const { + return cast<EnumDecl>(TagDecl::getMostRecentDecl()); + } + EnumDecl *getMostRecentDecl() { + return cast<EnumDecl>(TagDecl::getMostRecentDecl()); + } + + EnumDecl *getDefinition() const { + return cast_or_null<EnumDecl>(TagDecl::getDefinition()); } static EnumDecl *Create(ASTContext &C, DeclContext *DC, @@ -2651,7 +2751,7 @@ public: IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); - static EnumDecl *Create(ASTContext &C, EmptyShell Empty); + static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// completeDefinition - When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the @@ -2668,14 +2768,14 @@ public: typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; enumerator_iterator enumerator_begin() const { - const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + const EnumDecl *E = getDefinition(); if (!E) E = this; return enumerator_iterator(E->decls_begin()); } enumerator_iterator enumerator_end() const { - const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + const EnumDecl *E = getDefinition(); if (!E) E = this; return enumerator_iterator(E->decls_end()); @@ -2723,7 +2823,7 @@ public: /// \brief Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: - /// + /// /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS /// ------------------------ ------- ----------------- /// -1 1111111 1 @@ -2760,11 +2860,31 @@ public: /// \brief Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. - EnumDecl *getInstantiatedFromMemberEnum() const { - return InstantiatedFrom; + EnumDecl *getInstantiatedFromMemberEnum() const; + + /// \brief If this enumeration is a member of a specialization of a + /// templated class, determine what kind of template specialization + /// or instantiation this is. + TemplateSpecializationKind getTemplateSpecializationKind() const; + + /// \brief For an enumeration member that was instantiated from a member + /// enumeration of a templated class, set the template specialiation kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); + + /// \brief If this enumeration is an instantiation of a member enumeration of + /// a class template specialization, retrieves the member specialization + /// information. + MemberSpecializationInfo *getMemberSpecializationInfo() const { + return SpecializationInfo; } - void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } + /// \brief Specify that this enumeration is an instantiation of the + /// member enumeration ED. + void setInstantiationOfMemberEnum(EnumDecl *ED, + TemplateSpecializationKind TSK) { + setInstantiationOfMemberEnum(getASTContext(), ED, TSK); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumDecl *D) { return true; } @@ -2791,7 +2911,7 @@ class RecordDecl : public TagDecl { bool AnonymousStructOrUnion : 1; /// HasObjectMember - This is true if this struct has at least one member - /// containing an object. + /// containing an Objective-C object pointer type. bool HasObjectMember : 1; /// \brief Whether the field declarations of this record have been loaded @@ -2810,13 +2930,20 @@ public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl = 0); - static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); + static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - const RecordDecl *getPreviousDeclaration() const { - return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + const RecordDecl *getPreviousDecl() const { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl()); } - RecordDecl *getPreviousDeclaration() { - return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + RecordDecl *getPreviousDecl() { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl()); + } + + const RecordDecl *getMostRecentDecl() const { + return cast<RecordDecl>(TagDecl::getMostRecentDecl()); + } + RecordDecl *getMostRecentDecl() { + return cast<RecordDecl>(TagDecl::getMostRecentDecl()); } bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } @@ -2902,6 +3029,7 @@ private: }; class FileScopeAsmDecl : public Decl { + virtual void anchor(); StringLiteral *AsmString; SourceLocation RParenLoc; FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, @@ -2912,10 +3040,12 @@ public: StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc); + static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation getAsmLoc() const { return getLocation(); } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getAsmLoc(), getRParenLoc()); } @@ -2976,6 +3106,8 @@ private: // FIXME: This can be packed into the bitfields in Decl. bool IsVariadic : 1; bool CapturesCXXThis : 1; + bool BlockMissingReturnType : 1; + bool IsConversionFromLambda : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. @@ -2992,12 +3124,14 @@ protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), CapturesCXXThis(false), + BlockMissingReturnType(true), IsConversionFromLambda(false), ParamInfo(0), NumParams(0), Body(0), SignatureAsWritten(0), Captures(0), NumCaptures(0) {} public: - static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); - + static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); + static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation getCaretLocation() const { return getLocation(); } bool isVariadic() const { return IsVariadic; } @@ -3049,6 +3183,11 @@ public: capture_const_iterator capture_end() const { return Captures + NumCaptures; } bool capturesCXXThis() const { return CapturesCXXThis; } + bool blockMissingReturnType() const { return BlockMissingReturnType; } + void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; } + + bool isConversionFromLambda() const { return IsConversionFromLambda; } + void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; } bool capturesVariable(const VarDecl *var) const; @@ -3057,8 +3196,8 @@ public: const Capture *end, bool capturesCXXThis); - virtual SourceRange getSourceRange() const; - + virtual SourceRange getSourceRange() const LLVM_READONLY; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const BlockDecl *D) { return true; } @@ -3071,6 +3210,75 @@ public: } }; +/// \brief Describes a module import declaration, which makes the contents +/// of the named module visible in the current translation unit. +/// +/// An import declaration imports the named module (or submodule). For example: +/// \code +/// @__experimental_modules_import std.vector; +/// \endcode +/// +/// Import declarations can also be implicitly generated from #include/#import +/// directives. +class ImportDecl : public Decl { + /// \brief The imported module, along with a bit that indicates whether + /// we have source-location information for each identifier in the module + /// name. + /// + /// When the bit is false, we only have a single source location for the + /// end of the import declaration. + llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete; + + /// \brief The next import in the list of imports local to the translation + /// unit being parsed (not loaded from an AST file). + ImportDecl *NextLocalImport; + + friend class ASTReader; + friend class ASTDeclReader; + friend class ASTContext; + + ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs); + + ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, + SourceLocation EndLoc); + + ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { } + +public: + /// \brief Create a new module import declaration. + static ImportDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs); + + /// \brief Create a new module import declaration for an implicitly-generated + /// import. + static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + SourceLocation EndLoc); + + /// \brief Create a new, deserialized module import declaration. + static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumLocations); + + /// \brief Retrieve the module that was imported by the import declaration. + Module *getImportedModule() const { return ImportedAndComplete.getPointer(); } + + /// \brief Retrieves the locations of each of the identifiers that make up + /// the complete module name in the import declaration. + /// + /// This will return an empty array if the locations of the individual + /// identifiers aren't available. + ArrayRef<SourceLocation> getIdentifierLocs() const; + + virtual SourceRange getSourceRange() const LLVM_READONLY; + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ImportDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Import; } +}; + + /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -3079,6 +3287,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, DiagnosticsEngine::ak_nameddecl); return DB; } +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const NamedDecl* ND) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND), + DiagnosticsEngine::ak_nameddecl); + return PD; +} template<typename decl_type> void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { @@ -3086,26 +3300,44 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { // and Redeclarable to be defined. decl_type *First; - + if (PrevDecl) { // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. - RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( - PrevDecl->getMostRecentDeclaration())); + RedeclLink = PreviousDeclLink( + llvm::cast<decl_type>(PrevDecl->getMostRecentDecl())); First = PrevDecl->getFirstDeclaration(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); } else { // Make this first. First = static_cast<decl_type*>(this); } - + // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) ND->ClearLinkageCache(); } +// Inline function definitions. + +/// \brief Check if the given decl is complete. +/// +/// We use this function to break a cycle between the inline definitions in +/// Type.h and Decl.h. +inline bool IsEnumDeclComplete(EnumDecl *ED) { + return ED->isComplete(); +} + +/// \brief Check if the given decl is scoped. +/// +/// We use this function to break a cycle between the inline definitions in +/// Type.h and Decl.h. +inline bool IsEnumDeclScoped(EnumDecl *ED) { + return ED->isScoped(); +} + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h index 9f29411..4c675aed 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h @@ -17,8 +17,9 @@ #include "clang/AST/Attr.h" #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PrettyStackTrace.h" namespace clang { class DeclContext; @@ -98,7 +99,7 @@ public: /// identifiers. C++ describes lookup completely differently: /// certain lookups merely "ignore" certain kinds of declarations, /// usually based on whether the declaration is of a type, etc. - /// + /// /// These are meant as bitmasks, so that searches in /// C++ can look into the "tag" namespace during ordinary lookup. /// @@ -180,12 +181,28 @@ public: OBJC_TQ_Oneway = 0x20 }; -private: - /// NextDeclInContext - The next declaration within the same lexical +protected: + // Enumeration values used in the bits stored in NextInContextAndBits. + enum { + /// \brief Whether this declaration is a top-level declaration (function, + /// global variable, etc.) that is lexically inside an objc container + /// definition. + TopLevelDeclInObjCContainerFlag = 0x01, + + /// \brief Whether this declaration is private to the module in which it was + /// defined. + ModulePrivateFlag = 0x02 + }; + + /// \brief The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is /// traversed via DeclContext's decls_begin()/decls_end(). - Decl *NextDeclInContext; + /// + /// The extra two bits are used for the TopLevelDeclInObjCContainer and + /// ModulePrivate bits. + llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits; +private: friend class DeclContext; struct MultipleDC { @@ -243,7 +260,10 @@ private: /// evaluated context or not, e.g. functions used in uninstantiated templates /// are regarded as "referenced" but not "used". unsigned Referenced : 1; - + + /// \brief Whether statistic collection is enabled. + static bool StatisticsEnabled; + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum @@ -252,14 +272,12 @@ protected: /// \brief Whether this declaration was loaded from an AST file. unsigned FromASTFile : 1; - - /// ChangedAfterLoad - if this declaration has changed since being loaded - unsigned ChangedAfterLoad : 1; - - /// \brief Whether this declaration is private to the module in which it was - /// defined. - unsigned ModulePrivate : 1; + /// \brief Whether this declaration is hidden from normal name lookup, e.g., + /// because it is was loaded from an AST file is either module-private or + /// because its submodule has not been made visible. + unsigned Hidden : 1; + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 12; @@ -267,14 +285,15 @@ protected: /// /// This field is only valid for NamedDecls subclasses. mutable unsigned HasCachedLinkage : 1; - + /// \brief If \c HasCachedLinkage, the linkage of this declaration. /// /// This field is only valid for NamedDecls subclasses. mutable unsigned CachedLinkage : 2; - + friend class ASTDeclWriter; friend class ASTDeclReader; + friend class ASTReader; private: void CheckAccessDeclContext() const; @@ -282,38 +301,52 @@ private: protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextDeclInContext(0), DeclCtx(DC), + : NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), ChangedAfterLoad(false), - ModulePrivate(0), + Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + HasCachedLinkage(0) { - if (Decl::CollectingStats()) add(DK); + if (StatisticsEnabled) add(DK); } Decl(Kind DK, EmptyShell Empty) - : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), + : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), ChangedAfterLoad(false), - ModulePrivate(0), + Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) { - if (Decl::CollectingStats()) add(DK); + if (StatisticsEnabled) add(DK); } virtual ~Decl(); + /// \brief Allocate memory for a deserialized declaration. + /// + /// This routine must be used to allocate memory for any declaration that is + /// deserialized from a module file. + /// + /// \param Context The context in which we will allocate memory. + /// \param ID The global ID of the deserialized declaration. + /// \param Size The size of the allocated object. + static void *AllocateDeserializedDecl(const ASTContext &Context, + unsigned ID, + unsigned Size); + public: /// \brief Source range that this declaration covers. - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getLocation()); } - SourceLocation getLocStart() const { return getSourceRange().getBegin(); } - SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + SourceLocation getLocStart() const LLVM_READONLY { + return getSourceRange().getBegin(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSourceRange().getEnd(); + } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -321,8 +354,8 @@ public: Kind getKind() const { return static_cast<Kind>(DeclKind); } const char *getDeclKindName() const; - Decl *getNextDeclInContext() { return NextDeclInContext; } - const Decl *getNextDeclInContext() const { return NextDeclInContext; } + Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); } + const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();} DeclContext *getDeclContext() { if (isInSemaDC()) @@ -347,7 +380,7 @@ public: bool isInAnonymousNamespace() const; - ASTContext &getASTContext() const; + ASTContext &getASTContext() const LLVM_READONLY; void setAccess(AccessSpecifier AS) { Access = AS; @@ -364,7 +397,9 @@ public: } bool hasAttrs() const { return HasAttrs; } - void setAttrs(const AttrVec& Attrs); + void setAttrs(const AttrVec& Attrs) { + return setAttrsImpl(Attrs, getASTContext()); + } AttrVec &getAttrs() { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } @@ -389,11 +424,11 @@ public: attr_iterator attr_end() const { return hasAttrs() ? getAttrs().end() : 0; } - + template <typename T> void dropAttr() { if (!HasAttrs) return; - + AttrVec &Attrs = getAttrs(); for (unsigned i = 0, e = Attrs.size(); i != e; /* in loop */) { if (isa<T>(Attrs[i])) { @@ -406,7 +441,7 @@ public: if (Attrs.empty()) HasAttrs = false; } - + template <typename T> specific_attr_iterator<T> specific_attr_begin() const { return specific_attr_iterator<T>(attr_begin()); @@ -455,6 +490,48 @@ public: void setReferenced(bool R = true) { Referenced = R; } + /// \brief Whether this declaration is a top-level declaration (function, + /// global variable, etc.) that is lexically inside an objc container + /// definition. + bool isTopLevelDeclInObjCContainer() const { + return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag; + } + + void setTopLevelDeclInObjCContainer(bool V = true) { + unsigned Bits = NextInContextAndBits.getInt(); + if (V) + Bits |= TopLevelDeclInObjCContainerFlag; + else + Bits &= ~TopLevelDeclInObjCContainerFlag; + NextInContextAndBits.setInt(Bits); + } + +protected: + /// \brief Whether this declaration was marked as being private to the + /// module in which it was defined. + bool isModulePrivate() const { + return NextInContextAndBits.getInt() & ModulePrivateFlag; + } + + /// \brief Specify whether this declaration was marked as being private + /// to the module in which it was defined. + void setModulePrivate(bool MP = true) { + unsigned Bits = NextInContextAndBits.getInt(); + if (MP) + Bits |= ModulePrivateFlag; + else + Bits &= ~ModulePrivateFlag; + NextInContextAndBits.setInt(Bits); + } + + /// \brief Set the owning module ID. + void setOwningModuleID(unsigned ID) { + assert(isFromASTFile() && "Only works on a deserialized declaration"); + *((unsigned*)this - 2) = ID; + } + +public: + /// \brief Determine the availability of the given declaration. /// /// This routine will determine the most restrictive availability of @@ -504,20 +581,24 @@ public: /// \brief Determine whether this declaration came from an AST file (such as /// a precompiled header or module) rather than having been parsed. bool isFromASTFile() const { return FromASTFile; } - - /// \brief Query whether this declaration was changed in a significant way - /// since being loaded from an AST file. - /// - /// In an epic violation of layering, what is "significant" is entirely - /// up to the serialization system, but implemented in AST and Sema. - bool isChangedSinceDeserialization() const { return ChangedAfterLoad; } - /// \brief Mark this declaration as having changed since deserialization, or - /// reset the flag. - void setChangedSinceDeserialization(bool Changed) { - ChangedAfterLoad = Changed; + /// \brief Retrieve the global declaration ID associated with this + /// declaration, which specifies where in the + unsigned getGlobalID() const { + if (isFromASTFile()) + return *((const unsigned*)this - 1); + return 0; } - + + /// \brief Retrieve the global ID of the module that owns this particular + /// declaration. + unsigned getOwningModuleID() const { + if (isFromASTFile()) + return *((const unsigned*)this - 2); + + return 0; + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -587,7 +668,7 @@ public: /// \brief Whether this particular Decl is a canonical one. bool isCanonicalDecl() const { return getCanonicalDecl() == this; } - + protected: /// \brief Returns the next redeclaration or itself if this is the only decl. /// @@ -595,6 +676,14 @@ protected: /// Decl::redecl_iterator can iterate over them. virtual Decl *getNextRedeclaration() { return this; } + /// \brief Implementation of getPreviousDecl(), to be overridden by any + /// subclass that has a redeclaration chain. + virtual Decl *getPreviousDeclImpl() { return 0; } + + /// \brief Implementation of getMostRecentDecl(), to be overridden by any + /// subclass that has a redeclaration chain. + virtual Decl *getMostRecentDeclImpl() { return this; } + public: /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { @@ -645,6 +734,26 @@ public: } redecl_iterator redecls_end() const { return redecl_iterator(); } + /// \brief Retrieve the previous declaration that declares the same entity + /// as this declaration, or NULL if there is no previous declaration. + Decl *getPreviousDecl() { return getPreviousDeclImpl(); } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration, or NULL if there is no previous declaration. + const Decl *getPreviousDecl() const { + return const_cast<Decl *>(this)->getPreviousDeclImpl(); + } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration (which may be this declaration). + Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration (which may be this declaration). + const Decl *getMostRecentDecl() const { + return const_cast<Decl *>(this)->getMostRecentDeclImpl(); + } + /// getBody - If this Decl represents a declaration for a body of code, /// such as a function or method definition, this method returns the /// top-level Stmt* of that body. Otherwise this method returns null. @@ -660,7 +769,7 @@ public: // global temp stats (until we have a per-module visitor) static void add(Kind k); - static bool CollectingStats(bool Enable = false); + static void EnableStatistics(); static void PrintStats(); /// isTemplateParameter - Determines whether this declaration is a @@ -673,7 +782,7 @@ public: /// \brief Whether this declaration is a parameter pack. bool isParameterPack() const; - + /// \brief returns true if this declaration is a template bool isTemplateDecl() const; @@ -722,7 +831,7 @@ public: unsigned mask = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); if (!mask) return FOK_None; - return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared : FOK_Undeclared); } @@ -747,17 +856,31 @@ public: static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void dump() const; - void dumpXML() const; + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dumpXML() const; void dumpXML(raw_ostream &OS) const; private: const Attr *getAttrsImpl() const; + void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); + void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, + ASTContext &Ctx); protected: ASTMutationListener *getASTMutationListener() const; }; +/// \brief Determine whether two declarations declare the same entity. +inline bool declaresSameEntity(const Decl *D1, const Decl *D2) { + if (!D1 || !D2) + return false; + + if (D1 == D2) + return true; + + return D1->getCanonicalDecl() == D2->getCanonicalDecl(); +} + /// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when /// doing something to a specific decl. class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { @@ -826,8 +949,11 @@ class DeclContext { /// \brief Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a - /// dependent context). - mutable StoredDeclsMap *LookupPtr; + /// dependent context), and a bool indicating whether we have lazily + /// omitted any declarations from the map. We maintain the invariant + /// that, if the map contains an entry for a DeclarationName, then it + /// contains all relevant entries for that name. + mutable llvm::PointerIntPair<StoredDeclsMap*, 1, bool> LookupPtr; protected: /// FirstDecl - The first declaration stored within this declaration @@ -841,16 +967,17 @@ protected: mutable Decl *LastDecl; friend class ExternalASTSource; + friend class ASTWriter; /// \brief Build up a chain of declarations. /// /// \returns the first/last pair of declarations. static std::pair<Decl *, Decl *> - BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, bool FieldsAlreadyLoaded); + BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded); DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), - ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + ExternalVisibleStorage(false), LookupPtr(0, false), FirstDecl(0), LastDecl(0) { } public: @@ -886,11 +1013,11 @@ public: } DeclContext *getLookupParent(); - + const DeclContext *getLookupParent() const { return const_cast<DeclContext*>(this)->getLookupParent(); } - + ASTContext &getParentASTContext() const { return cast<Decl>(this)->getASTContext(); } @@ -974,6 +1101,14 @@ public: /// declaration context DC. bool Encloses(const DeclContext *DC) const; + /// \brief Find the nearest non-closure ancestor of this context, + /// i.e. the innermost semantic parent of this context which is not + /// a closure. A context may be its own non-closure ancestor. + DeclContext *getNonClosureAncestor(); + const DeclContext *getNonClosureAncestor() const { + return const_cast<DeclContext*>(this)->getNonClosureAncestor(); + } + /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with @@ -1007,24 +1142,30 @@ public: /// inline, its enclosing namespace, recursively. bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; - /// getNextContext - If this is a DeclContext that may have other - /// DeclContexts that are semantically connected but syntactically - /// different, such as C++ namespaces, this routine retrieves the - /// next DeclContext in the link. Iteration through the chain of - /// DeclContexts should begin at the primary DeclContext and - /// continue until this function returns NULL. For example, given: - /// @code + /// \\brief Collects all of the declaration contexts that are semantically + /// connected to this declaration context. + /// + /// For declaration contexts that have multiple semantically connected but + /// syntactically distinct contexts, such as C++ namespaces, this routine + /// retrieves the complete set of such declaration contexts in source order. + /// For example, given: + /// + /// \code /// namespace N { /// int x; /// } /// namespace N { /// int y; /// } - /// @endcode - /// The first occurrence of namespace N will be the primary - /// DeclContext. Its getNextContext will return the second - /// occurrence of namespace N. - DeclContext *getNextContext(); + /// \endcode + /// + /// The \c Contexts parameter will contain both definitions of N. + /// + /// \param Contexts Will be cleared and set to the set of declaration + /// contexts that are semanticaly connected to this declaration context, + /// in source order, including this context (which may be the only result, + /// for non-namespace contexts). + void collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts); /// decl_iterator - Iterates through the declarations stored /// within this context. @@ -1133,13 +1274,13 @@ public: return tmp; } - friend bool - operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) { + friend bool operator==(const specific_decl_iterator& x, + const specific_decl_iterator& y) { return x.Current == y.Current; } - friend bool - operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) { + friend bool operator!=(const specific_decl_iterator& x, + const specific_decl_iterator& y) { return x.Current != y.Current; } }; @@ -1207,13 +1348,13 @@ public: return tmp; } - friend bool - operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + friend bool operator==(const filtered_decl_iterator& x, + const filtered_decl_iterator& y) { return x.Current == y.Current; } - friend bool - operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + friend bool operator!=(const filtered_decl_iterator& x, + const filtered_decl_iterator& y) { return x.Current != y.Current; } }; @@ -1232,6 +1373,16 @@ public: /// semantic context via makeDeclVisibleInContext. void addDecl(Decl *D); + /// @brief Add the declaration D into this context, but suppress + /// searches for external declarations with the same name. + /// + /// Although analogous in function to addDecl, this removes an + /// important check. This is only useful if the Decl is being + /// added in response to an external search; in all other cases, + /// addDecl() is the right function to use. + /// See the ASTImporter for use cases. + void addDeclInternal(Decl *D); + /// @brief Add the declaration D to this context without modifying /// any lookup tables. /// @@ -1265,12 +1416,12 @@ public: /// \brief A simplistic name lookup mechanism that performs name lookup /// into this declaration context without consulting the external source. /// - /// This function should almost never be used, because it subverts the + /// This function should almost never be used, because it subverts the /// usual relationship between a DeclContext and the external source. /// See the ASTImporter for the (few, but important) use cases. - void localUncachedLookup(DeclarationName Name, + void localUncachedLookup(DeclarationName Name, llvm::SmallVectorImpl<NamedDecl *> &Results); - + /// @brief Makes a declaration visible within this context. /// /// This routine makes the declaration D visible to name lookup @@ -1285,11 +1436,15 @@ public: /// visible from this context, as determined by /// NamedDecl::declarationReplaces, the previous declaration will be /// replaced with D. - /// - /// @param Recoverable true if it's okay to not add this decl to - /// the lookup tables because it can be easily recovered by walking - /// the declaration chains. - void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); + void makeDeclVisibleInContext(NamedDecl *D); + + /// all_lookups_iterator - An iterator that provides a view over the results + /// of looking up every possible name. + class all_lookups_iterator; + + all_lookups_iterator lookups_begin() const; + + all_lookups_iterator lookups_end() const; /// udir_iterator - Iterates through the using-directives stored /// within this context. @@ -1315,7 +1470,11 @@ public: // Low-level accessors /// \brief Retrieve the internal representation of the lookup structure. - StoredDeclsMap* getLookupPtr() const { return LookupPtr; } + /// This may omit some names if we are lazily building the structure. + StoredDeclsMap *getLookupPtr() const { return LookupPtr.getPointer(); } + + /// \brief Ensure the lookup structure is fully-built and return it. + StoredDeclsMap *buildLookup(); /// \brief Whether this DeclContext has external storage containing /// additional declarations that are lexically in this context. @@ -1340,9 +1499,10 @@ public: /// \brief Determine whether the given declaration is stored in the list of /// declarations lexically within this context. bool isDeclInLexicalTraversal(const Decl *D) const { - return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl); + return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl || + D == LastDecl); } - + static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } #define DECL(NAME, BASE) @@ -1350,16 +1510,26 @@ public: static bool classof(const NAME##Decl *D) { return true; } #include "clang/AST/DeclNodes.inc" - void dumpDeclContext() const; + LLVM_ATTRIBUTE_USED void dumpDeclContext() const; private: void LoadLexicalDeclsFromExternalStorage() const; + /// @brief Makes a declaration visible within this context, but + /// suppresses searches for external declarations with the same + /// name. + /// + /// Analogous to makeDeclVisibleInContext, but for the exclusive + /// use of addDeclInternal(). + void makeDeclVisibleInContextInternal(NamedDecl *D); + friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; - void buildLookup(DeclContext *DCtx); - void makeDeclVisibleInContextImpl(NamedDecl *D); + void buildLookupImpl(DeclContext *DCtx); + void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, + bool Rediscoverable); + void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal); }; inline bool Decl::isTemplateParameter() const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h index 7e60773..7f3ec4c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h @@ -16,10 +16,14 @@ #define LLVM_CLANG_AST_DECLCXX_H #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/Decl.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -36,7 +40,8 @@ class CXXMemberLookupCriteria; class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class FriendDecl; - +class LambdaExpr; + /// \brief Represents any kind of function declaration, whether it is a /// concrete function or a function template. class AnyFunctionDecl { @@ -104,6 +109,7 @@ namespace clang { /// Also note that this class has nothing to do with so-called /// "access declarations" (C++98 11.3 [class.access.dcl]). class AccessSpecDecl : public Decl { + virtual void anchor(); /// ColonLoc - The location of the ':'. SourceLocation ColonLoc; @@ -125,7 +131,7 @@ public: /// setColonLoc - Sets the location of the colon. void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getAccessSpecifierLoc(), getColonLoc()); } @@ -134,9 +140,7 @@ public: SourceLocation ColonLoc) { return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); } - static AccessSpecDecl *Create(ASTContext &C, EmptyShell Empty) { - return new (C) AccessSpecDecl(Empty); - } + static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -170,7 +174,7 @@ class CXXBaseSpecifier { /// \brief The source location of the ellipsis, if this is a pack /// expansion. SourceLocation EllipsisLoc; - + /// Virtual - Whether this is a virtual base class or not. bool Virtual : 1; @@ -200,12 +204,14 @@ public: CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) - : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), + : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { } /// getSourceRange - Retrieves the source range that contains the /// entire base specifier. - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } /// isVirtual - Determines whether the base class is a virtual base /// class (or not). @@ -214,7 +220,7 @@ public: /// \brief Determine whether this base class is a base of a class declared /// with the 'class' keyword (vs. one declared with the 'struct' keyword). bool isBaseOfClass() const { return BaseOfClass; } - + /// \brief Determine whether this base specifier is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } @@ -319,7 +325,8 @@ class CXXRecordDecl : public RecordDecl { /// * has no non-static data members of type non-standard-layout class (or /// array of such types) or reference, /// * has no virtual functions (10.3) and no virtual base classes (10.1), - /// * has the same access control (Clause 11) for all non-static data members + /// * has the same access control (Clause 11) for all non-static data + /// members /// * has no non-standard-layout base classes, /// * either has no non-static data members in the most derived class and at /// most one base class with non-static data members, or has no base @@ -346,7 +353,10 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if this class (or any subobject) has mutable fields. bool HasMutableFields : 1; - + + /// \brief True if there no non-field members declared by the user. + bool HasOnlyCMembers : 1; + /// HasTrivialDefaultConstructor - True when, if this class has a default /// constructor, this default constructor is trivial. /// @@ -364,10 +374,34 @@ class CXXRecordDecl : public RecordDecl { bool HasTrivialDefaultConstructor : 1; /// HasConstexprNonCopyMoveConstructor - True when this class has at least - /// one constexpr constructor which is neither the copy nor move - /// constructor. + /// one user-declared constexpr constructor which is neither the copy nor + /// move constructor. bool HasConstexprNonCopyMoveConstructor : 1; + /// DefaultedDefaultConstructorIsConstexpr - True if a defaulted default + /// constructor for this class would be constexpr. + bool DefaultedDefaultConstructorIsConstexpr : 1; + + /// DefaultedCopyConstructorIsConstexpr - True if a defaulted copy + /// constructor for this class would be constexpr. + bool DefaultedCopyConstructorIsConstexpr : 1; + + /// DefaultedMoveConstructorIsConstexpr - True if a defaulted move + /// constructor for this class would be constexpr. + bool DefaultedMoveConstructorIsConstexpr : 1; + + /// HasConstexprDefaultConstructor - True if this class has a constexpr + /// default constructor (either user-declared or implicitly declared). + bool HasConstexprDefaultConstructor : 1; + + /// HasConstexprCopyConstructor - True if this class has a constexpr copy + /// constructor (either user-declared or implicitly declared). + bool HasConstexprCopyConstructor : 1; + + /// HasConstexprMoveConstructor - True if this class has a constexpr move + /// constructor (either user-declared or implicitly declared). + bool HasConstexprMoveConstructor : 1; + /// HasTrivialCopyConstructor - True when this class has a trivial copy /// constructor. /// @@ -438,8 +472,13 @@ class CXXRecordDecl : public RecordDecl { /// type (or array thereof), each such class has a trivial destructor. bool HasTrivialDestructor : 1; + /// HasIrrelevantDestructor - True when this class has a destructor with no + /// semantic effect. + bool HasIrrelevantDestructor : 1; + /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least - /// one non-static data member or base class of non literal type. + /// one non-static data member or base class of non-literal or volatile + /// type. bool HasNonLiteralTypeFieldsOrBases : 1; /// ComputedVisibleConversions - True when visible conversion functions are @@ -458,13 +497,13 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether we have already declared the move constructor. bool DeclaredMoveConstructor : 1; - + /// \brief Whether we have already declared the copy-assignment operator. bool DeclaredCopyAssignment : 1; /// \brief Whether we have already declared the move-assignment operator. bool DeclaredMoveAssignment : 1; - + /// \brief Whether we have already declared a destructor within the class. bool DeclaredDestructor : 1; @@ -476,9 +515,12 @@ class CXXRecordDecl : public RecordDecl { /// declared but would have been deleted. bool FailedImplicitMoveAssignment : 1; + /// \brief Whether this class describes a C++ lambda. + bool IsLambda : 1; + /// NumBases - The number of base class specifiers in Bases. unsigned NumBases; - + /// NumVBases - The number of virtual base class specifiers in VBases. unsigned NumVBases; @@ -510,17 +552,59 @@ class CXXRecordDecl : public RecordDecl { /// in reverse order. FriendDecl *FirstFriend; - /// \brief Retrieve the set of direct base classes. + /// \brief Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { return Bases.get(Definition->getASTContext().getExternalSource()); } - /// \brief Retrieve the set of virtual base classes. + /// \brief Retrieve the set of virtual base classes. CXXBaseSpecifier *getVBases() const { return VBases.get(Definition->getASTContext().getExternalSource()); } } *DefinitionData; + /// \brief Describes a C++ closure type (generated by a lambda expression). + struct LambdaDefinitionData : public DefinitionData { + typedef LambdaExpr::Capture Capture; + + LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) + : DefinitionData(D), Dependent(Dependent), NumCaptures(0), + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) + { + IsLambda = true; + } + + /// \brief Whether this lambda is known to be dependent, even if its + /// context isn't dependent. + /// + /// A lambda with a non-dependent context can be dependent if it occurs + /// within the default argument of a function template, because the + /// lambda will have been created with the enclosing context as its + /// declaration context, rather than function. This is an unfortunate + /// artifact of having to parse the default arguments before + unsigned Dependent : 1; + + /// \brief The number of captures in this lambda. + unsigned NumCaptures : 16; + + /// \brief The number of explicit captures in this lambda. + unsigned NumExplicitCaptures : 15; + + /// \brief The number used to indicate this lambda expression for name + /// mangling in the Itanium C++ ABI. + unsigned ManglingNumber; + + /// \brief The declaration that provides context for this lambda, if the + /// actual DeclContext does not suffice. This is used for lambdas that + /// occur within default arguments of function parameters within the class + /// or within a data member initializer. + Decl *ContextDecl; + + /// \brief The list of captures, both explicit and implicit, for this + /// lambda. + Capture *Captures; + }; + struct DefinitionData &data() { assert(DefinitionData && "queried property of class with no definition"); return *DefinitionData; @@ -530,6 +614,13 @@ class CXXRecordDecl : public RecordDecl { assert(DefinitionData && "queried property of class with no definition"); return *DefinitionData; } + + struct LambdaDefinitionData &getLambdaData() const { + assert(DefinitionData && "queried property of lambda with no definition"); + assert(DefinitionData->IsLambda && + "queried lambda property of non-lambda class"); + return static_cast<LambdaDefinitionData &>(*DefinitionData); + } /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. @@ -538,23 +629,26 @@ class CXXRecordDecl : public RecordDecl { /// declarations that describe a class template, this will be a /// pointer to a ClassTemplateDecl. For member /// classes of class template specializations, this will be the - /// MemberSpecializationInfo referring to the member class that was + /// MemberSpecializationInfo referring to the member class that was /// instantiated or specialized. llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> TemplateOrInstantiation; friend class DeclContext; - + friend class LambdaExpr; + /// \brief Notify the class that member has been added. /// - /// This routine helps maintain information about the class based on which + /// This routine helps maintain information about the class based on which /// members have been added. It will be invoked by DeclContext::addDecl() /// whenever a member is added to this record. void addedMember(Decl *D); void markedVirtualFunctionPure(); friend void FunctionDecl::setPure(bool); - + + friend class ASTNodeImporter; + protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -585,12 +679,19 @@ public: virtual const CXXRecordDecl *getCanonicalDecl() const { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } - - const CXXRecordDecl *getPreviousDeclaration() const { - return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration()); + + const CXXRecordDecl *getPreviousDecl() const { + return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDecl()); } - CXXRecordDecl *getPreviousDeclaration() { - return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration()); + CXXRecordDecl *getPreviousDecl() { + return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDecl()); + } + + const CXXRecordDecl *getMostRecentDecl() const { + return cast_or_null<CXXRecordDecl>(RecordDecl::getMostRecentDecl()); + } + CXXRecordDecl *getMostRecentDecl() { + return cast_or_null<CXXRecordDecl>(RecordDecl::getMostRecentDecl()); } CXXRecordDecl *getDefinition() const { @@ -604,7 +705,9 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); - static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty); + static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, + SourceLocation Loc, bool DependentLambda); + static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; @@ -704,7 +807,7 @@ public: /// /// This value is used for lazy creation of default constructors. bool needsImplicitDefaultConstructor() const { - return !data().UserDeclaredConstructor && + return !data().UserDeclaredConstructor && !data().DeclaredDefaultConstructor; } @@ -722,11 +825,11 @@ public: CXXConstructorDecl *getCopyConstructor(unsigned TypeQuals) const; /// getMoveConstructor - Returns the move constructor for this class - CXXConstructorDecl *getMoveConstructor() const; + CXXConstructorDecl *getMoveConstructor() const; /// \brief Retrieve the copy-assignment operator for this class, if available. /// - /// This routine attempts to find the copy-assignment operator for this + /// This routine attempts to find the copy-assignment operator for this /// class, using a simplistic form of overload resolution. /// /// \param ArgIsConst Whether the argument to the copy-assignment operator @@ -739,7 +842,7 @@ public: /// getMoveAssignmentOperator - Returns the move assignment operator for this /// class CXXMethodDecl *getMoveAssignmentOperator() const; - + /// hasUserDeclaredConstructor - Whether this class has any /// user-declared constructors. When true, a default constructor /// will not be implicitly declared. @@ -760,7 +863,7 @@ public: return data().UserDeclaredCopyConstructor; } - /// \brief Determine whether this class has had its copy constructor + /// \brief Determine whether this class has had its copy constructor /// declared, either via the user or via an implicit declaration. /// /// This value is used for lazy creation of copy constructors. @@ -822,7 +925,7 @@ public: return data().UserDeclaredCopyAssignment; } - /// \brief Determine whether this class has had its copy assignment operator + /// \brief Determine whether this class has had its copy assignment operator /// declared, either via the user or via an implicit declaration. /// /// This value is used for lazy creation of copy assignment operators. @@ -882,6 +985,29 @@ public: /// This value is used for lazy creation of destructors. bool hasDeclaredDestructor() const { return data().DeclaredDestructor; } + /// \brief Determine whether this class describes a lambda function object. + bool isLambda() const { return hasDefinition() && data().IsLambda; } + + /// \brief For a closure type, retrieve the mapping from captured + /// variables and this to the non-static data members that store the + /// values or references of the captures. + /// + /// \param Captures Will be populated with the mapping from captured + /// variables to the corresponding fields. + /// + /// \param ThisCapture Will be set to the field declaration for the + /// 'this' capture. + void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, + FieldDecl *&ThisCapture) const; + + typedef const LambdaExpr::Capture* capture_const_iterator; + capture_const_iterator captures_begin() const { + return isLambda() ? getLambdaData().Captures : NULL; + } + capture_const_iterator captures_end() const { + return isLambda() ? captures_begin() + getLambdaData().NumCaptures : NULL; + } + /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. UnresolvedSetImpl *getConversionFunctions() { @@ -920,6 +1046,10 @@ public: /// user-defined destructor. bool isPOD() const { return data().PlainOldData; } + /// \brief True if this class is C-like, without C++-specific features, e.g. + /// it contains only public fields, no bases, tag kind is not 'class', etc. + bool isCLike() const; + /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which /// means it has a virtual function, virtual base, data member (other than /// 0-width bit-field) or inherits from a non-empty class. Does NOT include @@ -941,20 +1071,63 @@ public: /// \brief Whether this class, or any of its class subobjects, contains a /// mutable field. bool hasMutableFields() const { return data().HasMutableFields; } - - // hasTrivialDefaultConstructor - Whether this class has a trivial default - // constructor - // (C++0x [class.ctor]p5) + + /// hasTrivialDefaultConstructor - Whether this class has a trivial default + /// constructor (C++11 [class.ctor]p5). bool hasTrivialDefaultConstructor() const { return data().HasTrivialDefaultConstructor && (!data().UserDeclaredConstructor || data().DeclaredDefaultConstructor); } - // hasConstexprNonCopyMoveConstructor - Whether this class has at least one - // constexpr constructor other than the copy or move constructors. + /// hasConstexprNonCopyMoveConstructor - Whether this class has at least one + /// constexpr constructor other than the copy or move constructors. bool hasConstexprNonCopyMoveConstructor() const { - return data().HasConstexprNonCopyMoveConstructor; + return data().HasConstexprNonCopyMoveConstructor || + (!hasUserDeclaredConstructor() && + defaultedDefaultConstructorIsConstexpr()); + } + + /// defaultedDefaultConstructorIsConstexpr - Whether a defaulted default + /// constructor for this class would be constexpr. + bool defaultedDefaultConstructorIsConstexpr() const { + return data().DefaultedDefaultConstructorIsConstexpr; + } + + /// defaultedCopyConstructorIsConstexpr - Whether a defaulted copy + /// constructor for this class would be constexpr. + bool defaultedCopyConstructorIsConstexpr() const { + return data().DefaultedCopyConstructorIsConstexpr; + } + + /// defaultedMoveConstructorIsConstexpr - Whether a defaulted move + /// constructor for this class would be constexpr. + bool defaultedMoveConstructorIsConstexpr() const { + return data().DefaultedMoveConstructorIsConstexpr; + } + + /// hasConstexprDefaultConstructor - Whether this class has a constexpr + /// default constructor. + bool hasConstexprDefaultConstructor() const { + return data().HasConstexprDefaultConstructor || + (!data().UserDeclaredConstructor && + data().DefaultedDefaultConstructorIsConstexpr && isLiteral()); + } + + /// hasConstexprCopyConstructor - Whether this class has a constexpr copy + /// constructor. + bool hasConstexprCopyConstructor() const { + return data().HasConstexprCopyConstructor || + (!data().DeclaredCopyConstructor && + data().DefaultedCopyConstructorIsConstexpr && isLiteral()); + } + + /// hasConstexprMoveConstructor - Whether this class has a constexpr move + /// constructor. + bool hasConstexprMoveConstructor() const { + return data().HasConstexprMoveConstructor || + (needsImplicitMoveConstructor() && + data().DefaultedMoveConstructorIsConstexpr && isLiteral()); } // hasTrivialCopyConstructor - Whether this class has a trivial copy @@ -985,8 +1158,15 @@ public: // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } - // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type - // non-static data member or base class. + // hasIrrelevantDestructor - Whether this class has a destructor which has no + // semantic effect. Any such destructor will be trivial, public, defaulted + // and not deleted, and will call only irrelevant destructors. + bool hasIrrelevantDestructor() const { + return data().HasIrrelevantDestructor; + } + + // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or + // volatile type non-static data member or base class. bool hasNonLiteralTypeFieldsOrBases() const { return data().HasNonLiteralTypeFieldsOrBases; } @@ -1006,20 +1186,23 @@ public: // isLiteral - Whether this class is a literal type. // - // C++0x [basic.types]p10 + // C++11 [basic.types]p10 // A class type that has all the following properties: - // -- a trivial destructor + // -- it has a trivial destructor // -- every constructor call and full-expression in the // brace-or-equal-intializers for non-static data members (if any) is // a constant expression. // -- it is an aggregate type or has at least one constexpr constructor or // constructor template that is not a copy or move constructor, and - // -- all non-static data members and base classes of literal types + // -- all of its non-static data members and base classes are of literal + // types // - // We resolve DR1361 by ignoring the second bullet. + // We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by + // treating types with trivial default constructors as literal types. bool isLiteral() const { return hasTrivialDestructor() && - (isAggregate() || hasConstexprNonCopyMoveConstructor()) && + (isAggregate() || hasConstexprNonCopyMoveConstructor() || + hasTrivialDefaultConstructor()) && !hasNonLiteralTypeFieldsOrBases(); } @@ -1043,12 +1226,12 @@ public: /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberClass(). CXXRecordDecl *getInstantiatedFromMemberClass() const; - + /// \brief If this class is an instantiation of a member class of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - + /// \brief Specify that this record is an instantiation of the /// member class RD. void setInstantiationOfMemberClass(CXXRecordDecl *RD, @@ -1077,7 +1260,7 @@ public: /// instantiation of a class template or member class of a class template, /// and how it was instantiated or specialized. TemplateSpecializationKind getTemplateSpecializationKind() const; - + /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); @@ -1104,7 +1287,7 @@ public: /// /// \returns true if this class is derived from Base, false otherwise. bool isDerivedFrom(const CXXRecordDecl *Base) const; - + /// \brief Determine whether this class is derived from the type \p Base. /// /// This routine only determines whether this class is derived from \p Base, @@ -1119,8 +1302,8 @@ public: /// /// \returns true if this class is derived from Base, false otherwise. /// - /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than - /// tangling input and output in \p Paths + /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than + /// tangling input and output in \p Paths bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; /// \brief Determine whether this class is virtually derived from @@ -1155,20 +1338,20 @@ public: /// /// The class itself does not count as a base class. This routine /// returns false if the class has non-computable base classes. - /// + /// /// \param AllowShortCircuit if false, forces the callback to be called /// for every base class, even if a dependent or non-matching base was /// found. bool forallBases(ForallBasesCallback *BaseMatches, void *UserData, bool AllowShortCircuit = true) const; - - /// \brief Function type used by lookupInBases() to determine whether a + + /// \brief Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. /// - /// \param Specifier the base-class specifier that describes the inheritance + /// \param Specifier the base-class specifier that describes the inheritance /// from the base class we are trying to match. /// - /// \param Path the current path, from the most-derived class down to the + /// \param Path the current path, from the most-derived class down to the /// base named by the \p Specifier. /// /// \param UserData a single pointer to user-specified data, provided to @@ -1178,13 +1361,13 @@ public: typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); - + /// \brief Look for entities within the base classes of this C++ class, /// transitively searching all base class subobjects. /// - /// This routine uses the callback function \p BaseMatches to find base + /// This routine uses the callback function \p BaseMatches to find base /// classes meeting some search criteria, walking all base class subobjects - /// and populating the given \p Paths structure with the paths through the + /// and populating the given \p Paths structure with the paths through the /// inheritance hierarchy that resulted in a match. On a successful search, /// the \p Paths structure can be queried to retrieve the matching paths and /// to determine if there were any ambiguities. @@ -1201,7 +1384,7 @@ public: /// subobject that matches the search criteria. bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const; - + /// \brief Base-class lookup callback that determines whether the given /// base class specifier refers to a specific class declaration. /// @@ -1223,7 +1406,7 @@ public: /// 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. /// @@ -1241,7 +1424,7 @@ public: /// is an opaque \c DeclarationName pointer. static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name); - + /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. /// @@ -1277,15 +1460,15 @@ public: /// \brief Indicates that the definition of this class is now complete. virtual void completeDefinition(); - /// \brief Indicates that the definition of this class is now complete, + /// \brief Indicates that the definition of this class is now complete, /// and provides a final overrider map to help determine - /// + /// /// \param FinalOverriders The final overrider map for this class, which can /// be provided as an optimization for abstract-class checking. If NULL, /// final overriders will be computed if they are needed to complete the /// definition. void completeDefinition(CXXFinalOverriderMap *FinalOverriders); - + /// \brief Determine whether this class may end up being abstract, even though /// it is not yet known to be abstract. /// @@ -1294,6 +1477,53 @@ public: /// will need to compute final overriders to determine whether the class is /// actually abstract. bool mayBeAbstract() const; + + /// \brief If this is the closure type of a lambda expression, retrieve the + /// number to be used for name mangling in the Itanium C++ ABI. + /// + /// Zero indicates that this closure type has internal linkage, so the + /// mangling number does not matter, while a non-zero value indicates which + /// lambda expression this is in this particular context. + unsigned getLambdaManglingNumber() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().ManglingNumber; + } + + /// \brief Retrieve the declaration that provides additional context for a + /// lambda, when the normal declaration context is not specific enough. + /// + /// Certain contexts (default arguments of in-class function parameters and + /// the initializers of data members) have separate name mangling rules for + /// lambdas within the Itanium C++ ABI. For these cases, this routine provides + /// the declaration in which the lambda occurs, e.g., the function parameter + /// or the non-static data member. Otherwise, it returns NULL to imply that + /// the declaration context suffices. + Decl *getLambdaContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().ContextDecl; + } + + /// \brief Set the mangling number and context declaration for a lambda + /// class. + void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) { + getLambdaData().ManglingNumber = ManglingNumber; + getLambdaData().ContextDecl = ContextDecl; + } + + /// \brief Determine whether this lambda expression was known to be dependent + /// at the time it was created, even if its context does not appear to be + /// dependent. + /// + /// This flag is a workaround for an issue with parsing, where default + /// arguments are parsed before their enclosing function declarations have + /// been created. This means that any lambda expressions within those + /// default arguments will have as their DeclContext the context enclosing + /// the function declaration, which may be non-dependent even when the + /// function declaration itself is dependent. This flag indicates when we + /// know that the lambda is dependent despite that. + bool isDependentLambda() const { + return isLambda() && getLambdaData().Dependent; + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { @@ -1313,6 +1543,7 @@ public: /// CXXMethodDecl - Represents a static or instance method of a /// struct/union/class. class CXXMethodDecl : public FunctionDecl { + virtual void anchor(); protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -1322,9 +1553,9 @@ protected: : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None), SCAsWritten, isInline, isConstexpr) { - if (EndLocation.isValid()) - setRangeEnd(EndLocation); - } + if (EndLocation.isValid()) + setRangeEnd(EndLocation); + } public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -1337,16 +1568,18 @@ public: bool isConstexpr, SourceLocation EndLocation); + static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); + bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } bool isVirtual() const { - CXXMethodDecl *CD = + CXXMethodDecl *CD = cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); if (CD->isVirtualAsWritten()) return true; - + return (CD->begin_overridden_methods() != CD->end_overridden_methods()); } @@ -1354,14 +1587,14 @@ public: /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded /// delete or delete[] operator with a particular signature. bool isUsualDeallocationFunction() const; - + /// \brief Determine whether this is a copy-assignment operator, regardless /// of whether it was declared implicitly or explicitly. bool isCopyAssignmentOperator() const; /// \brief Determine whether this is a move assignment operator. bool isMoveAssignmentOperator() const; - + const CXXMethodDecl *getCanonicalDecl() const { return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); } @@ -1374,11 +1607,11 @@ public: bool isUserProvided() const { return !(isDeleted() || getCanonicalDecl()->isDefaulted()); } - + /// void addOverriddenMethod(const CXXMethodDecl *MD); - typedef const CXXMethodDecl ** method_iterator; + typedef const CXXMethodDecl *const* method_iterator; method_iterator begin_overridden_methods() const; method_iterator end_overridden_methods() const; @@ -1419,9 +1652,18 @@ public: RefQualifierKind getRefQualifier() const { return getType()->getAs<FunctionProtoType>()->getRefQualifier(); } - + bool hasInlineBody() const; + /// \brief Determine whether this is a lambda closure type's static member + /// function that is used for the result of the lambda's conversion to + /// function pointer (for a lambda with no captures). + /// + /// The function itself, if used, will have a placeholder body that will be + /// supplied by IR generation to either forward to the function call operator + /// or clone the function call operator. + bool isLambdaStaticInvoker() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXMethodDecl *D) { return true; } @@ -1445,31 +1687,34 @@ public: /// }; /// @endcode class CXXCtorInitializer { - /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target - /// constructor (CXXConstructorDecl*) being initialized. - llvm::PointerUnion4<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *, - CXXConstructorDecl *> + /// \brief Either the base class name/delegating constructor type (stored as + /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field + /// (IndirectFieldDecl*) being initialized. + llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> Initializee; - + /// \brief The source location for the field name or, for a base initializer /// pack expansion, the location of the ellipsis. In the case of a delegating /// constructor, it will still include the type's source location as the /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; - + /// \brief The argument used to initialize the base or member, which may /// end up constructing an object (when multiple arguments are involved). - /// If 0, this is a field initializer, and the in-class member initializer + /// If 0, this is a field initializer, and the in-class member initializer /// will be used. Stmt *Init; - + /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; /// RParenLoc - Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; + /// \brief If the initializee is a type, whether that type makes this + /// a delegating initialization. + bool IsDelegating : 1; + /// IsVirtual - If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. bool IsVirtual : 1; @@ -1483,12 +1728,12 @@ class CXXCtorInitializer { /// original sources, counting from 0; otherwise, if IsWritten is false, /// it stores the number of array index variables stored after this /// object in memory. - unsigned SourceOrderOrNumArrayIndices : 14; + unsigned SourceOrderOrNumArrayIndices : 13; CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R, VarDecl **Indices, unsigned NumIndices); - + public: /// CXXCtorInitializer - Creates a new base-class initializer. explicit @@ -1510,25 +1755,27 @@ public: /// CXXCtorInitializer - Creates a new delegating Initializer. explicit - CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, - CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, + SourceLocation L, Expr *Init, SourceLocation R); - /// \brief Creates a new member initializer that optionally contains + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R, VarDecl **Indices, unsigned NumIndices); - + /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. - bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); } + bool isBaseInitializer() const { + return Initializee.is<TypeSourceInfo*>() && !IsDelegating; + } /// isMemberInitializer - Returns true when this initializer is /// initializing a non-static data member. bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); } - bool isAnyMemberInitializer() const { + bool isAnyMemberInitializer() const { return isMemberInitializer() || isIndirectMemberInitializer(); } @@ -1546,21 +1793,21 @@ public: /// isDelegatingInitializer - Returns true when this initializer is creating /// a delegating constructor. bool isDelegatingInitializer() const { - return Initializee.is<CXXConstructorDecl *>(); + return Initializee.is<TypeSourceInfo*>() && IsDelegating; } /// \brief Determine whether this initializer is a pack expansion. - bool isPackExpansion() const { - return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); + bool isPackExpansion() const { + return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); } - + // \brief For a pack expansion, returns the location of the ellipsis. SourceLocation getEllipsisLoc() const { assert(isPackExpansion() && "Initializer is not a pack expansion"); return MemberOrEllipsisLocation; } - - /// If this is a base class initializer, returns the type of the + + /// If this is a base class initializer, returns the type of the /// base class with location information. Otherwise, returns an NULL /// type location. TypeLoc getBaseClassLoc() const; @@ -1572,56 +1819,47 @@ public: /// Returns whether the base is virtual or not. bool isBaseVirtual() const { assert(isBaseInitializer() && "Must call this on base initializer!"); - + return IsVirtual; } - /// \brief Returns the declarator information for a base class initializer. - TypeSourceInfo *getBaseClassInfo() const { + /// \brief Returns the declarator information for a base class or delegating + /// initializer. + TypeSourceInfo *getTypeSourceInfo() const { return Initializee.dyn_cast<TypeSourceInfo *>(); } - + /// getMember - If this is a member initializer, returns the /// declaration of the non-static data member being /// initialized. Otherwise, returns NULL. FieldDecl *getMember() const { if (isMemberInitializer()) return Initializee.get<FieldDecl*>(); - else - return 0; + return 0; } FieldDecl *getAnyMember() const { if (isMemberInitializer()) return Initializee.get<FieldDecl*>(); - else if (isIndirectMemberInitializer()) + if (isIndirectMemberInitializer()) return Initializee.get<IndirectFieldDecl*>()->getAnonField(); - else - return 0; + return 0; } IndirectFieldDecl *getIndirectMember() const { if (isIndirectMemberInitializer()) return Initializee.get<IndirectFieldDecl*>(); - else - return 0; + return 0; } - CXXConstructorDecl *getTargetConstructor() const { - if (isDelegatingInitializer()) - return Initializee.get<CXXConstructorDecl*>(); - else - return 0; - } - - SourceLocation getMemberLocation() const { + SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } - + /// \brief Determine the source location of the initializer. SourceLocation getSourceLocation() const; - + /// \brief Determine the source range covering the entire initializer. - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; /// isWritten - Returns true if this initializer is explicitly written /// in the source code. @@ -1656,7 +1894,7 @@ public: return IsWritten ? 0 : SourceOrderOrNumArrayIndices; } - /// \brief Retrieve a particular array index variable used to + /// \brief Retrieve a particular array index variable used to /// describe an array member initialization. VarDecl *getArrayIndex(unsigned I) { assert(I < getNumArrayIndices() && "Out of bounds member array index"); @@ -1670,7 +1908,12 @@ public: assert(I < getNumArrayIndices() && "Out of bounds member array index"); reinterpret_cast<VarDecl **>(this + 1)[I] = Index; } - + ArrayRef<VarDecl *> getArrayIndexes() { + assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); + return ArrayRef<VarDecl *>(reinterpret_cast<VarDecl **>(this + 1), + getNumArrayIndices()); + } + /// \brief Get the initializer. This is 0 if this is an in-class initializer /// for a non-static data member which has not yet been parsed. Expr *getInit() const { @@ -1691,6 +1934,7 @@ public: /// }; /// @endcode class CXXConstructorDecl : public CXXMethodDecl { + virtual void anchor(); /// IsExplicitSpecified - Whether this constructor declaration has the /// 'explicit' keyword specified. bool IsExplicitSpecified : 1; @@ -1712,7 +1956,7 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isExplicitSpecified, bool isInline, + bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared, bool isConstexpr) : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, SC_None, isInline, isConstexpr, SourceLocation()), @@ -1722,7 +1966,7 @@ class CXXConstructorDecl : public CXXMethodDecl { } public: - static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); + static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -1734,7 +1978,7 @@ public: /// isExplicitSpecified - Whether this constructor declaration has the /// 'explicit' keyword specified. bool isExplicitSpecified() const { return IsExplicitSpecified; } - + /// isExplicit - Whether this constructor was marked "explicit" or not. bool isExplicit() const { return cast<CXXConstructorDecl>(getFirstDeclaration()) @@ -1782,7 +2026,8 @@ public: } typedef std::reverse_iterator<init_iterator> init_reverse_iterator; - typedef std::reverse_iterator<init_const_iterator> init_const_reverse_iterator; + typedef std::reverse_iterator<init_const_iterator> + init_const_reverse_iterator; init_reverse_iterator init_rbegin() { return init_reverse_iterator(init_end()); @@ -1821,11 +2066,7 @@ public: /// getTargetConstructor - When this constructor delegates to /// another, retrieve the target - CXXConstructorDecl *getTargetConstructor() const { - assert(isDelegatingConstructor() && - "A non-delegating constructor has no target"); - return CtorInitializers[0]->getTargetConstructor(); - } + CXXConstructorDecl *getTargetConstructor() const; /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to @@ -1902,12 +2143,12 @@ public: CXXConstructorDecl *getCanonicalDecl() { return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl()); } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -1922,6 +2163,7 @@ public: /// }; /// @endcode class CXXDestructorDecl : public CXXMethodDecl { + virtual void anchor(); /// ImplicitlyDefined - Whether this destructor was implicitly /// defined by the compiler. When false, the destructor was defined /// by the user. In C++03, this flag will have the same value as @@ -1931,7 +2173,7 @@ class CXXDestructorDecl : public CXXMethodDecl { bool ImplicitlyDefined : 1; FunctionDecl *OperatorDelete; - + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, @@ -1943,13 +2185,13 @@ class CXXDestructorDecl : public CXXMethodDecl { } public: - static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo* TInfo, bool isInline, bool isImplicitlyDeclared); + static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); /// isImplicitlyDefined - Whether this destructor was implicitly /// defined. If false, then this destructor was defined by the @@ -1957,7 +2199,8 @@ public: /// already been defined. bool isImplicitlyDefined() const { assert(isThisDeclarationADefinition() && - "Can only get the implicit-definition flag once the destructor has been defined"); + "Can only get the implicit-definition flag once the destructor has " + "been defined"); return ImplicitlyDefined; } @@ -1965,7 +2208,8 @@ public: /// implicitly defined or not. void setImplicitlyDefined(bool ID) { assert(isThisDeclarationADefinition() && - "Can only set the implicit-definition flag once the destructor has been defined"); + "Can only set the implicit-definition flag once the destructor has " + "been defined"); ImplicitlyDefined = ID; } @@ -1976,7 +2220,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -1991,7 +2235,8 @@ public: /// }; /// @endcode class CXXConversionDecl : public CXXMethodDecl { - /// IsExplicitSpecified - Whether this conversion function declaration is + virtual void anchor(); + /// IsExplicitSpecified - Whether this conversion function declaration is /// marked "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; @@ -2006,7 +2251,6 @@ class CXXConversionDecl : public CXXMethodDecl { IsExplicitSpecified(isExplicitSpecified) { } public: - static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -2014,8 +2258,9 @@ public: bool isInline, bool isExplicit, bool isConstexpr, SourceLocation EndLocation); + static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// IsExplicitSpecified - Whether this conversion function declaration is + /// IsExplicitSpecified - Whether this conversion function declaration is /// marked "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. bool isExplicitSpecified() const { return IsExplicitSpecified; } @@ -2034,11 +2279,15 @@ public: return getType()->getAs<FunctionType>()->getResultType(); } + /// \brief Determine whether this conversion function is a conversion from + /// a lambda closure type to a block pointer. + bool isLambdaToBlockPointerConversion() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -2047,6 +2296,7 @@ public: /// extern "C" void foo(); /// class LinkageSpecDecl : public Decl, public DeclContext { + virtual void anchor(); public: /// LanguageIDs - Used to represent the language in a linkage /// specification. The values are part of the serialization abi for @@ -2076,7 +2326,8 @@ public: SourceLocation ExternLoc, SourceLocation LangLoc, LanguageIDs Lang, SourceLocation RBraceLoc = SourceLocation()); - + static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } /// \brief Set the language specified by this linkage specification. @@ -2091,7 +2342,7 @@ public: void setExternLoc(SourceLocation L) { ExternLoc = L; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - SourceLocation getLocEnd() const { + SourceLocation getLocEnd() const LLVM_READONLY { if (hasBraces()) return getRBraceLoc(); // No braces: get the end location of the (only) declaration in context @@ -2099,7 +2350,7 @@ public: return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(ExternLoc, getLocEnd()); } @@ -2119,12 +2370,13 @@ public: /// using namespace std; /// // NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide -// artificial name, for all using-directives in order to store +// artificial names for all using-directives in order to store // them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { + virtual void anchor(); /// \brief The location of the "using" keyword. SourceLocation UsingLoc; - + /// SourceLocation - Location of 'namespace' token. SourceLocation NamespaceLoc; @@ -2159,11 +2411,11 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } @@ -2185,7 +2437,7 @@ public: /// \brief Return the location of the "using" keyword. SourceLocation getUsingLoc() const { return UsingLoc; } - + // FIXME: Could omit 'Key' in name. /// getNamespaceKeyLocation - Returns location of namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } @@ -2200,18 +2452,19 @@ public: SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor); - - SourceRange getSourceRange() const { + static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(UsingLoc, getLocation()); } - + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDirectiveDecl *D) { return true; } static bool classofKind(Kind K) { return K == UsingDirective; } // Friend for getUsingDirectiveName. friend class DeclContext; - + friend class ASTDeclReader; }; @@ -2221,15 +2474,17 @@ public: /// namespace Foo = Bar; /// @endcode class NamespaceAliasDecl : public NamedDecl { + virtual void anchor(); + /// \brief The location of the "namespace" keyword. SourceLocation NamespaceLoc; /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. SourceLocation IdentLoc; - + /// \brief The nested-name-specifier that precedes the namespace. NestedNameSpecifierLoc QualifierLoc; - + /// Namespace - The Decl that this alias points to. Can either be a /// NamespaceDecl or a NamespaceAliasDecl. NamedDecl *Namespace; @@ -2238,23 +2493,23 @@ class NamespaceAliasDecl : public NamedDecl { SourceLocation AliasLoc, IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), + : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), QualifierLoc(QualifierLoc), Namespace(Namespace) { } friend class ASTDeclReader; - + public: /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } - + /// \brief Retrieve the namespace declaration aliased by this directive. NamespaceDecl *getNamespace() { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) @@ -2282,17 +2537,19 @@ public: NamedDecl *getAliasedNamespace() const { return Namespace; } static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, + SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace); - virtual SourceRange getSourceRange() const { + static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(NamespaceLoc, IdentLoc); } - + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceAliasDecl *D) { return true; } static bool classofKind(Kind K) { return K == NamespaceAlias; } @@ -2310,6 +2567,8 @@ public: /// } /// class UsingShadowDecl : public NamedDecl { + virtual void anchor(); + /// The referenced declaration. NamedDecl *Underlying; @@ -2337,6 +2596,8 @@ public: return new (C) UsingShadowDecl(DC, Loc, Using, Target); } + static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// \brief Gets the underlying declaration which has been brought into the /// local scope. NamedDecl *getTargetDecl() const { return Underlying; } @@ -2369,6 +2630,8 @@ public: /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { + virtual void anchor(); + /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; @@ -2380,18 +2643,16 @@ class UsingDecl : public NamedDecl { DeclarationNameLoc DNLoc; /// \brief The first shadow declaration of the shadow decl chain associated - /// with this using declaration. - UsingShadowDecl *FirstUsingShadow; + /// with this using declaration. The bool member of the pair store whether + /// this decl has the 'typename' keyword. + llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow; - // \brief Has 'typename' keyword. - bool IsTypeName; - - UsingDecl(DeclContext *DC, SourceLocation UL, + UsingDecl(DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) { + DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, IsTypeNameArg) { } public: @@ -2406,8 +2667,8 @@ public: NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } DeclarationNameInfo getNameInfo() const { @@ -2415,10 +2676,10 @@ public: } /// \brief Return true if the using declaration has 'typename'. - bool isTypeName() const { return IsTypeName; } + bool isTypeName() const { return FirstUsingShadow.getInt(); } /// \brief Sets whether the using declaration has 'typename'. - void setTypeName(bool TN) { IsTypeName = TN; } + void setTypeName(bool TN) { FirstUsingShadow.setInt(TN); } /// \brief Iterates through the using shadow declarations assosiated with /// this using declaration. @@ -2459,7 +2720,7 @@ public: }; shadow_iterator shadow_begin() const { - return shadow_iterator(FirstUsingShadow); + return shadow_iterator(FirstUsingShadow.getPointer()); } shadow_iterator shadow_end() const { return shadow_iterator(); } @@ -2478,7 +2739,9 @@ public: const DeclarationNameInfo &NameInfo, bool IsTypeNameArg); - SourceRange getSourceRange() const { + static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(UsingLocation, getNameInfo().getEndLoc()); } @@ -2499,6 +2762,8 @@ public: /// using Base<T>::foo; /// }; class UnresolvedUsingValueDecl : public ValueDecl { + virtual void anchor(); + /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; @@ -2510,7 +2775,7 @@ class UnresolvedUsingValueDecl : public ValueDecl { DeclarationNameLoc DNLoc; UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, - SourceLocation UsingLoc, + SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) : ValueDecl(UnresolvedUsingValue, DC, @@ -2531,20 +2796,23 @@ public: NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } - + DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - NestedNameSpecifierLoc QualifierLoc, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo); - SourceRange getSourceRange() const { + static UnresolvedUsingValueDecl * + CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(UsingLocation, getNameInfo().getEndLoc()); } @@ -2566,6 +2834,8 @@ public: /// The type associated with a unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { + virtual void anchor(); + /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; @@ -2578,14 +2848,14 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TargetNameLoc, + SourceLocation TargetNameLoc, IdentifierInfo *TargetName) : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, UsingLoc), TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; - + public: /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return getLocStart(); } @@ -2598,8 +2868,8 @@ public: NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } static UnresolvedUsingTypenameDecl * @@ -2607,6 +2877,9 @@ public: SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName); + static UnresolvedUsingTypenameDecl * + CreateDeserialized(ASTContext &C, unsigned ID); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } @@ -2614,6 +2887,7 @@ public: /// StaticAssertDecl - Represents a C++0x static_assert declaration. class StaticAssertDecl : public Decl { + virtual void anchor(); Expr *AssertExpr; StringLiteral *Message; SourceLocation RParenLoc; @@ -2629,7 +2903,8 @@ public: SourceLocation StaticAssertLoc, Expr *AssertExpr, StringLiteral *Message, SourceLocation RParenLoc); - + static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); + Expr *getAssertExpr() { return AssertExpr; } const Expr *getAssertExpr() const { return AssertExpr; } @@ -2639,7 +2914,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getRParenLoc()); } @@ -2655,6 +2930,9 @@ public: const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, AccessSpecifier AS); +const PartialDiagnostic &operator<<(const PartialDiagnostic &DB, + AccessSpecifier AS); + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h index b84e5bb..ba1eb8d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_DECLFRIEND_H #include "clang/AST/DeclCXX.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -35,6 +36,7 @@ namespace clang { /// /// The semantic context of a friend decl is its declaring class. class FriendDecl : public Decl { + virtual void anchor(); public: typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; @@ -77,7 +79,7 @@ public: static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL); - static FriendDecl *Create(ASTContext &C, EmptyShell Empty); + static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// If this friend declaration names an (untemplated but possibly /// dependent) type, return the type; otherwise return null. This @@ -99,7 +101,7 @@ public: } /// Retrieves the source range for the friend declaration. - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { /* FIXME: consider the case of templates wrt start of range. */ if (NamedDecl *ND = getFriendDecl()) return SourceRange(getFriendLoc(), ND->getLocEnd()); diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h new file mode 100644 index 0000000..66d190f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h @@ -0,0 +1,84 @@ +//===-- DeclLookups.h - Low-level interface to all names in a DC-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines DeclContext::all_lookups_iterator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLLOOKUPS_H +#define LLVM_CLANG_AST_DECLLOOKUPS_H + +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclContextInternals.h" +#include "clang/AST/DeclarationName.h" + +namespace clang { + +/// all_lookups_iterator - An iterator that provides a view over the results +/// of looking up every possible name. +class DeclContext::all_lookups_iterator { + StoredDeclsMap::iterator It, End; +public: + typedef lookup_result value_type; + typedef lookup_result reference; + typedef lookup_result pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + all_lookups_iterator() {} + all_lookups_iterator(StoredDeclsMap::iterator It, + StoredDeclsMap::iterator End) + : It(It), End(End) {} + + reference operator*() const { return It->second.getLookupResult(); } + pointer operator->() const { return It->second.getLookupResult(); } + + all_lookups_iterator& operator++() { + // Filter out using directives. They don't belong as results from name + // lookup anyways, except as an implementation detail. Users of the API + // should not expect to get them (or worse, rely on it). + do { + ++It; + } while (It != End && + It->first == DeclarationName::getUsingDirectiveName()); + + return *this; + } + + all_lookups_iterator operator++(int) { + all_lookups_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) { + return x.It == y.It; + } + friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) { + return x.It != y.It; + } +}; + +DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { + DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); + if (StoredDeclsMap *Map = Primary->buildLookup()) + return all_lookups_iterator(Map->begin(), Map->end()); + return all_lookups_iterator(); +} + +DeclContext::all_lookups_iterator DeclContext::lookups_end() const { + DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); + if (StoredDeclsMap *Map = Primary->buildLookup()) + return all_lookups_iterator(Map->end(), Map->end()); + return all_lookups_iterator(); +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h index 425c89d..4ae073e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/SelectorLocationsKind.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" namespace clang { class Expr; @@ -84,7 +85,7 @@ public: loc_iterator loc_begin() const { return Locations; } loc_iterator loc_end() const { return Locations + size(); } - void set(ObjCProtocolDecl* const* InList, unsigned Elts, + void set(ObjCProtocolDecl* const* InList, unsigned Elts, const SourceLocation *Locs, ASTContext &Ctx); }; @@ -124,7 +125,7 @@ private: // Synthesized declaration method for a property setter/getter unsigned IsSynthesized : 1; - + // Method has a definition. unsigned IsDefined : 1; @@ -144,14 +145,14 @@ private: /// \brief Indicates whether this method has a related result type. unsigned RelatedResultType : 1; - + /// \brief Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. unsigned SelLocsKind : 2; // Result type of this method. QualType MethodDeclType; - + // Type source information for the result type. TypeSourceInfo *ResultTInfo; @@ -246,7 +247,7 @@ public: SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, - QualType T, + QualType T, TypeSourceInfo *ResultTInfo, DeclContext *contextDecl, bool isInstance = true, @@ -257,6 +258,8 @@ public: ImplementationControl impControl = None, bool HasRelatedResultType = false); + static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); + virtual ObjCMethodDecl *getCanonicalDecl(); const ObjCMethodDecl *getCanonicalDecl() const { return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl(); @@ -270,23 +273,27 @@ public: /// \brief Determine whether this method has a result type that is related /// to the message receiver's type. bool hasRelatedResultType() const { return RelatedResultType; } - + /// \brief Note whether this method has a related result type. void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; } /// \brief True if this is a method redeclaration in the same interface. bool isRedeclaration() const { return IsRedeclaration; } void setAsRedeclaration(const ObjCMethodDecl *PrevMethod); - + // Location information, modeled after the Stmt API. - SourceLocation getLocStart() const { return getLocation(); } - SourceLocation getLocEnd() const { return EndLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } void setEndLoc(SourceLocation Loc) { EndLoc = Loc; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), EndLoc); } - SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); } + SourceLocation getSelectorStartLoc() const { + if (isImplicit()) + return getLocStart(); + return getSelectorLoc(0); + } SourceLocation getSelectorLoc(unsigned Index) const { assert(Index < getNumSelectorLocs() && "Index out of range!"); if (hasStandardSelLocs()) @@ -319,12 +326,12 @@ public: QualType getResultType() const { return MethodDeclType; } void setResultType(QualType T) { MethodDeclType = T; } - /// \brief Determine the type of an expression that sends a message to this + /// \brief Determine the type of an expression that sends a message to this /// function. QualType getSendResultType() const { return getResultType().getNonLValueExprType(getASTContext()); } - + TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; } void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; } @@ -338,8 +345,8 @@ public: param_iterator param_end() { return getParams() + NumParams; } // This method returns and of the parameters which are part of the selector // name mangling requirements. - param_const_iterator sel_param_end() const { - return param_begin() + getSelector().getNumArgs(); + param_const_iterator sel_param_end() const { + return param_begin() + getSelector().getNumArgs(); } /// \brief Sets the method's parameters and selector source locations. @@ -385,7 +392,7 @@ public: bool isSynthesized() const { return IsSynthesized; } void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } - + bool isDefined() const { return IsDefined; } void setDefined(bool isDefined) { IsDefined = isDefined; } @@ -426,6 +433,8 @@ public: /// ObjCProtocolDecl, and ObjCImplDecl. /// class ObjCContainerDecl : public NamedDecl, public DeclContext { + virtual void anchor(); + SourceLocation AtStart; // These two locations in the range mark the end of the method container. @@ -499,7 +508,7 @@ public: AtEnd = atEnd; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtStart, getAtEndRange().getEnd()); } @@ -540,64 +549,113 @@ public: /// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes /// typically inherit from NSObject (an exception is NSProxy). /// -class ObjCInterfaceDecl : public ObjCContainerDecl { +class ObjCInterfaceDecl : public ObjCContainerDecl + , public Redeclarable<ObjCInterfaceDecl> { + virtual void anchor(); + /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType mutable const Type *TypeForDecl; friend class ASTContext; + + struct DefinitionData { + /// \brief The definition of this class, for quick access from any + /// declaration. + ObjCInterfaceDecl *Definition; + + /// Class's super class. + ObjCInterfaceDecl *SuperClass; - /// Class's super class. - ObjCInterfaceDecl *SuperClass; + /// Protocols referenced in the @interface declaration + ObjCProtocolList ReferencedProtocols; - /// Protocols referenced in the @interface declaration - ObjCProtocolList ReferencedProtocols; - - /// Protocols reference in both the @interface and class extensions. - ObjCList<ObjCProtocolDecl> AllReferencedProtocols; + /// Protocols reference in both the @interface and class extensions. + ObjCList<ObjCProtocolDecl> AllReferencedProtocols; - /// \brief List of categories and class extensions defined for this class. - /// - /// Categories are stored as a linked list in the AST, since the categories - /// and class extensions come long after the initial interface declaration, - /// and we avoid dynamically-resized arrays in the AST wherever possible. - ObjCCategoryDecl *CategoryList; - - /// IvarList - List of all ivars defined by this class; including class - /// extensions and implementation. This list is built lazily. - ObjCIvarDecl *IvarList; + /// \brief List of categories and class extensions defined for this class. + /// + /// Categories are stored as a linked list in the AST, since the categories + /// and class extensions come long after the initial interface declaration, + /// and we avoid dynamically-resized arrays in the AST wherever possible. + ObjCCategoryDecl *CategoryList; - bool ForwardDecl:1; // declared with @class. - bool InternalInterface:1; // true - no @interface for @implementation - - /// \brief Indicates that the contents of this Objective-C class will be - /// completed by the external AST source when required. - mutable bool ExternallyCompleted : 1; - - SourceLocation SuperClassLoc; // location of the super class identifier. - SourceLocation EndLoc; // marks the '>', '}', or identifier. + /// IvarList - List of all ivars defined by this class; including class + /// extensions and implementation. This list is built lazily. + ObjCIvarDecl *IvarList; + + /// \brief Indicates that the contents of this Objective-C class will be + /// completed by the external AST source when required. + mutable bool ExternallyCompleted : 1; + + /// \brief The location of the superclass, if any. + SourceLocation SuperClassLoc; + + /// \brief The location of the last location in this declaration, before + /// the properties/methods. For example, this will be the '>', '}', or + /// identifier, + SourceLocation EndLoc; + + DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(), + ExternallyCompleted() { } + }; ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal); + SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, + bool isInternal); void LoadExternalDefinition() const; + + /// \brief Contains a pointer to the data associated with this class, + /// which will be NULL if this class has not yet been defined. + DefinitionData *Data; + + DefinitionData &data() const { + assert(Data != 0 && "Declaration has no definition!"); + return *Data; + } + + /// \brief Allocate the definition data for this class. + void allocateDefinitionData(); + + typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base; + virtual ObjCInterfaceDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual ObjCInterfaceDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual ObjCInterfaceDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: - static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, + static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc = SourceLocation(), - bool ForwardDecl = false, bool isInternal = false); - + + static ObjCInterfaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + virtual SourceRange getSourceRange() const LLVM_READONLY { + if (isThisDeclarationADefinition()) + return ObjCContainerDecl::getSourceRange(); + + return SourceRange(getAtStartLoc(), getLocation()); + } + /// \brief Indicate that this Objective-C class is complete, but that /// the external AST source will be responsible for filling in its contents /// when a complete class is required. void setExternallyCompleted(); - + const ObjCProtocolList &getReferencedProtocols() const { - if (ExternallyCompleted) + assert(hasDefinition() && "Caller did not check for forward reference!"); + if (data().ExternallyCompleted) LoadExternalDefinition(); - - return ReferencedProtocols; + + return data().ReferencedProtocols; } ObjCImplementationDecl *getImplementation() const; @@ -614,108 +672,182 @@ public: } typedef ObjCProtocolList::iterator protocol_iterator; - + protocol_iterator protocol_begin() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.begin(); + return data().ReferencedProtocols.begin(); } protocol_iterator protocol_end() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.end(); + return data().ReferencedProtocols.end(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - protocol_loc_iterator protocol_loc_begin() const { - if (ExternallyCompleted) + protocol_loc_iterator protocol_loc_begin() const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_loc_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.loc_begin(); + return data().ReferencedProtocols.loc_begin(); } - protocol_loc_iterator protocol_loc_end() const { - if (ExternallyCompleted) + protocol_loc_iterator protocol_loc_end() const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_loc_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.loc_end(); + return data().ReferencedProtocols.loc_end(); } - + typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; - + all_protocol_iterator all_referenced_protocol_begin() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return all_protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return AllReferencedProtocols.empty() ? protocol_begin() - : AllReferencedProtocols.begin(); + return data().AllReferencedProtocols.empty() + ? protocol_begin() + : data().AllReferencedProtocols.begin(); } all_protocol_iterator all_referenced_protocol_end() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return all_protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return AllReferencedProtocols.empty() ? protocol_end() - : AllReferencedProtocols.end(); + return data().AllReferencedProtocols.empty() + ? protocol_end() + : data().AllReferencedProtocols.end(); } 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()); } + ivar_iterator ivar_begin() const { + if (const ObjCInterfaceDecl *Def = getDefinition()) + return ivar_iterator(Def->decls_begin()); + + // FIXME: Should make sure no callers ever do this. + return ivar_iterator(); + } + ivar_iterator ivar_end() const { + if (const ObjCInterfaceDecl *Def = getDefinition()) + return ivar_iterator(Def->decls_end()); + + // FIXME: Should make sure no callers ever do this. + return ivar_iterator(); + } unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } - + bool ivar_empty() const { return ivar_begin() == ivar_end(); } - + ObjCIvarDecl *all_declared_ivar_begin(); const ObjCIvarDecl *all_declared_ivar_begin() const { // Even though this modifies IvarList, it's conceptually const: // the ivar chain is essentially a cached property of ObjCInterfaceDecl. return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin(); } - void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; } - + void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; } + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, const SourceLocation *Locs, ASTContext &C) { - ReferencedProtocols.set(List, Num, Locs, C); + data().ReferencedProtocols.set(List, Num, Locs, C); } /// mergeClassExtensionProtocolList - Merge class extension's protocol list /// into the protocol list for this class. - void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, + void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num, ASTContext &C); - bool isForwardDecl() const { return ForwardDecl; } - void setForwardDecl(bool val) { ForwardDecl = val; } + /// \brief Determine whether this particular declaration of this class is + /// actually also a definition. + bool isThisDeclarationADefinition() const { + return Data && Data->Definition == this; + } + + /// \brief Determine whether this class has been defined. + bool hasDefinition() const { return Data; } + + /// \brief Retrieve the definition of this class, or NULL if this class + /// has been forward-declared (with @class) but not yet defined (with + /// @interface). + ObjCInterfaceDecl *getDefinition() { + return hasDefinition()? Data->Definition : 0; + } + + /// \brief Retrieve the definition of this class, or NULL if this class + /// has been forward-declared (with @class) but not yet defined (with + /// @interface). + const ObjCInterfaceDecl *getDefinition() const { + return hasDefinition()? Data->Definition : 0; + } - ObjCInterfaceDecl *getSuperClass() const { - if (ExternallyCompleted) + /// \brief Starts the definition of this Objective-C class, taking it from + /// a forward declaration (@class) to a definition (@interface). + void startDefinition(); + + ObjCInterfaceDecl *getSuperClass() const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return SuperClass; + return data().SuperClass; + } + + void setSuperClass(ObjCInterfaceDecl * superCls) { + data().SuperClass = + (superCls && superCls->hasDefinition()) ? superCls->getDefinition() + : superCls; } - - void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } - ObjCCategoryDecl* getCategoryList() const { - if (ExternallyCompleted) + ObjCCategoryDecl* getCategoryList() const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return CategoryList; + return data().CategoryList; } - + void setCategoryList(ObjCCategoryDecl *category) { - CategoryList = category; + data().CategoryList = category; } - + ObjCCategoryDecl* getFirstClassExtension() const; ObjCPropertyDecl @@ -726,8 +858,9 @@ public: bool isSuperClassOf(const ObjCInterfaceDecl *I) const { // If RHS is derived from LHS it is OK; else it is not OK. while (I != NULL) { - if (this == I) + if (declaresSameEntity(this, I)) return true; + I = I->getSuperClass(); } return false; @@ -742,7 +875,20 @@ public: return true; Class = Class->getSuperClass(); } - return false; + return false; + } + + /// isObjCRequiresPropertyDefs - Checks that a class or one of its super + /// classes must not be auto-synthesized. Returns class decl. if it must not be; + /// 0, otherwise. + const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const { + const ObjCInterfaceDecl *Class = this; + while (Class) { + if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>()) + return Class; + Class = Class->getSuperClass(); + } + return 0; } ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, @@ -754,31 +900,39 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const; - ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { - return lookupMethod(Sel, true/*isInstance*/); + ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, + bool shallowCategoryLookup= false) const; + ObjCMethodDecl *lookupInstanceMethod(Selector Sel, + bool shallowCategoryLookup = false) const { + return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup); } - ObjCMethodDecl *lookupClassMethod(Selector Sel) const { - return lookupMethod(Sel, false/*isInstance*/); + ObjCMethodDecl *lookupClassMethod(Selector Sel, + bool shallowCategoryLookup = false) const { + return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup); } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); - + // Lookup a method in the classes implementation hierarchy. ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true); - // Location information, modeled after the Stmt API. - SourceLocation getLocStart() const { return getAtStartLoc(); } // '@'interface - SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; } + SourceLocation getEndOfDefinitionLoc() const { + if (!hasDefinition()) + return getLocation(); + + return data().EndLoc; + } + + void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; } - void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; } - SourceLocation getSuperClassLoc() const { return SuperClassLoc; } + void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; } + SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; } /// isImplicitInterfaceDecl - check that this is an implicitly declared /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation /// declaration without an @interface declaration. - bool isImplicitInterfaceDecl() const { return InternalInterface; } - void setImplicitInterfaceDecl(bool val) { InternalInterface = val; } + bool isImplicitInterfaceDecl() const { + return hasDefinition() ? Data->Definition->isImplicit() : isImplicit(); + } /// ClassImplementsProtocol - Checks that 'lProto' protocol /// has been implemented in IDecl class, its super class or categories (if @@ -787,6 +941,20 @@ public: bool lookupCategory, bool RHSIsQualifiedID = false); + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; + + /// Retrieves the canonical declaration of this Objective-C class. + ObjCInterfaceDecl *getCanonicalDecl() { + return getFirstDeclaration(); + } + const ObjCInterfaceDecl *getCanonicalDecl() const { + return getFirstDeclaration(); + } + // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } @@ -795,6 +963,7 @@ public: static bool classof(const ObjCInterfaceDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCInterface; } + friend class ASTReader; friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -815,6 +984,8 @@ public: /// } /// class ObjCIvarDecl : public FieldDecl { + virtual void anchor(); + public: enum AccessControl { None, Private, Protected, Public, Package @@ -837,12 +1008,14 @@ public: AccessControl ac, Expr *BW = NULL, bool synthesized=false); + static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// \brief Return the class interface that this ivar is logically contained /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. const ObjCInterfaceDecl *getContainingInterface() const; - + ObjCIvarDecl *getNextIvar() { return NextIvar; } const ObjCIvarDecl *getNextIvar() const { return NextIvar; } void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } @@ -857,16 +1030,16 @@ public: void setSynthesize(bool synth) { Synthesized = synth; } bool getSynthesize() const { return Synthesized; } - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCIvarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCIvar; } private: - /// NextIvar - Next Ivar in the list of ivars declared in class; class's + /// NextIvar - Next Ivar in the list of ivars declared in class; class's /// extensions and class's implementation ObjCIvarDecl *NextIvar; - + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; unsigned Synthesized : 1; @@ -876,7 +1049,7 @@ private: /// ObjCAtDefsFieldDecl - Represents a field declaration created by an /// @defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { -private: + virtual void anchor(); ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) @@ -890,6 +1063,8 @@ public: SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW); + static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } @@ -920,46 +1095,94 @@ public: /// /// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; /// -class ObjCProtocolDecl : public ObjCContainerDecl { - /// Referenced protocols - ObjCProtocolList ReferencedProtocols; +class ObjCProtocolDecl : public ObjCContainerDecl, + public Redeclarable<ObjCProtocolDecl> { + virtual void anchor(); - bool isForwardProtoDecl; // declared with @protocol. + struct DefinitionData { + // \brief The declaration that defines this protocol. + ObjCProtocolDecl *Definition; - SourceLocation EndLoc; // marks the '>' or identifier. + /// \brief Referenced protocols + ObjCProtocolList ReferencedProtocols; + }; + + DefinitionData *Data; - ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, - SourceLocation nameLoc, SourceLocation atStartLoc) - : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), - isForwardProtoDecl(true) { + DefinitionData &data() const { + assert(Data && "Objective-C protocol has no definition!"); + return *Data; } + + ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, + SourceLocation nameLoc, SourceLocation atStartLoc, + ObjCProtocolDecl *PrevDecl); + void allocateDefinitionData(); + + typedef Redeclarable<ObjCProtocolDecl> redeclarable_base; + virtual ObjCProtocolDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual ObjCProtocolDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual ObjCProtocolDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, - SourceLocation atStartLoc); + SourceLocation atStartLoc, + ObjCProtocolDecl *PrevDecl); + static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID); + const ObjCProtocolList &getReferencedProtocols() const { - return ReferencedProtocols; + assert(hasDefinition() && "No definition available!"); + return data().ReferencedProtocols; } typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } + protocol_iterator protocol_begin() const { + if (!hasDefinition()) + return protocol_iterator(); + + return data().ReferencedProtocols.begin(); + } + protocol_iterator protocol_end() const { + if (!hasDefinition()) + return protocol_iterator(); + + return data().ReferencedProtocols.end(); + } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - protocol_loc_iterator protocol_loc_begin() const { - return ReferencedProtocols.loc_begin(); + protocol_loc_iterator protocol_loc_begin() const { + if (!hasDefinition()) + return protocol_loc_iterator(); + + return data().ReferencedProtocols.loc_begin(); + } + protocol_loc_iterator protocol_loc_end() const { + if (!hasDefinition()) + return protocol_loc_iterator(); + + return data().ReferencedProtocols.loc_end(); } - protocol_loc_iterator protocol_loc_end() const { - return ReferencedProtocols.loc_end(); + unsigned protocol_size() const { + if (!hasDefinition()) + return 0; + + return data().ReferencedProtocols.size(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, const SourceLocation *Locs, ASTContext &C) { - ReferencedProtocols.set(List, Num, Locs, C); + assert(Data && "Protocol is not defined"); + data().ReferencedProtocols.set(List, Num, Locs, C); } ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); @@ -973,102 +1196,57 @@ public: ObjCMethodDecl *lookupClassMethod(Selector Sel) const { return lookupMethod(Sel, false/*isInstance*/); } - - bool isForwardDecl() const { return isForwardProtoDecl; } - void setForwardDecl(bool val) { isForwardProtoDecl = val; } - // Location information, modeled after the Stmt API. - SourceLocation getLocStart() const { return getAtStartLoc(); } // '@'protocol - SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; } + /// \brief Determine whether this protocol has a definition. + bool hasDefinition() const { return Data != 0; } - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCProtocolDecl *D) { return true; } - static bool classofKind(Kind K) { return K == ObjCProtocol; } -}; + /// \brief Retrieve the definition of this protocol, if any. + ObjCProtocolDecl *getDefinition() { + return Data? Data->Definition : 0; + } -/// ObjCClassDecl - Specifies a list of forward class declarations. For example: -/// -/// @class NSCursor, NSImage, NSPasteboard, NSWindow; -/// -class ObjCClassDecl : public Decl { -public: - class ObjCClassRef { - ObjCInterfaceDecl *ID; - SourceLocation L; - public: - ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {} - SourceLocation getLocation() const { return L; } - ObjCInterfaceDecl *getInterface() const { return ID; } - }; -private: - ObjCClassRef *ForwardDecl; + /// \brief Retrieve the definition of this protocol, if any. + const ObjCProtocolDecl *getDefinition() const { + return Data? Data->Definition : 0; + } - ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const Elt, const SourceLocation Loc, - ASTContext &C); -public: - static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const Elt = 0, - const SourceLocation Locs = SourceLocation()); - - ObjCInterfaceDecl *getForwardInterfaceDecl() { return ForwardDecl->getInterface(); } - ObjCClassRef *getForwardDecl() { return ForwardDecl; } - void setClass(ASTContext &C, ObjCInterfaceDecl*const Cls, - const SourceLocation Locs); + /// \brief Determine whether this particular declaration is also the + /// definition. + bool isThisDeclarationADefinition() const { + return getDefinition() == this; + } - virtual SourceRange getSourceRange() const; - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCClassDecl *D) { return true; } - static bool classofKind(Kind K) { return K == ObjCClass; } -}; - -/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations. -/// For example: -/// -/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo; -/// -class ObjCForwardProtocolDecl : public Decl { - ObjCProtocolList ReferencedProtocols; - - ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, - ObjCProtocolDecl *const *Elts, unsigned nElts, - const SourceLocation *Locs, ASTContext &C); - -public: - static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - ObjCProtocolDecl *const *Elts, - unsigned Num, - const SourceLocation *Locs); + /// \brief Starts the definition of this Objective-C protocol. + void startDefinition(); - static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L) { - return Create(C, DC, L, 0, 0, 0); + virtual SourceRange getSourceRange() const LLVM_READONLY { + if (isThisDeclarationADefinition()) + return ObjCContainerDecl::getSourceRange(); + + return SourceRange(getAtStartLoc(), getLocation()); } + + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; - typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - protocol_loc_iterator protocol_loc_begin() const { - return ReferencedProtocols.loc_begin(); + /// Retrieves the canonical declaration of this Objective-C protocol. + ObjCProtocolDecl *getCanonicalDecl() { + return getFirstDeclaration(); } - protocol_loc_iterator protocol_loc_end() const { - return ReferencedProtocols.loc_end(); + const ObjCProtocolDecl *getCanonicalDecl() const { + return getFirstDeclaration(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } - - /// setProtocolList - Set the list of forward protocols. - void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num, - const SourceLocation *Locs, ASTContext &C) { - ReferencedProtocols.set(List, Num, Locs, C); - } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCForwardProtocolDecl *D) { return true; } - static bool classofKind(Kind K) { return K == ObjCForwardProtocol; } + static bool classof(const ObjCProtocolDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCProtocol; } + + friend class ASTReader; + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// ObjCCategoryDecl - Represents a category declaration. A category allows @@ -1089,6 +1267,8 @@ public: /// don't support this level of dynamism, which is both powerful and dangerous. /// class ObjCCategoryDecl : public ObjCContainerDecl { + virtual void anchor(); + /// Interface belonging to this category ObjCInterfaceDecl *ClassInterface; @@ -1105,22 +1285,31 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// \brief The location of the category name in this declaration. SourceLocation CategoryNameLoc; - ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, + /// class extension may have private ivars. + SourceLocation IvarLBraceLoc; + SourceLocation IvarRBraceLoc; + + ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, - IdentifierInfo *Id, ObjCInterfaceDecl *IDecl) + IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), ClassInterface(IDecl), NextClassCategory(0), HasSynthBitfield(false), - CategoryNameLoc(CategoryNameLoc) { + CategoryNameLoc(CategoryNameLoc), + IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { } public: static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation AtLoc, + SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, - ObjCInterfaceDecl *IDecl); - static ObjCCategoryDecl *Create(ASTContext &C, EmptyShell Empty); + ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()); + static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID); ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } @@ -1144,21 +1333,21 @@ public: protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } unsigned protocol_size() const { return ReferencedProtocols.size(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - protocol_loc_iterator protocol_loc_begin() const { - return ReferencedProtocols.loc_begin(); + protocol_loc_iterator protocol_loc_begin() const { + return ReferencedProtocols.loc_begin(); } - protocol_loc_iterator protocol_loc_end() const { - return ReferencedProtocols.loc_end(); + protocol_loc_iterator protocol_loc_end() const { + return ReferencedProtocols.loc_end(); } ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } bool IsClassExtension() const { return getIdentifier() == 0; } const ObjCCategoryDecl *getNextClassExtension() const; - + bool hasSynthBitfield() const { return HasSynthBitfield; } void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } - + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1175,6 +1364,11 @@ public: SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; } + + void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } + SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } + void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } + SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCategoryDecl *D) { return true; } @@ -1185,6 +1379,8 @@ public: }; class ObjCImplDecl : public ObjCContainerDecl { + virtual void anchor(); + /// Class interface for this class/category implementation ObjCInterfaceDecl *ClassInterface; @@ -1248,28 +1444,36 @@ public: /// /// ObjCCategoryImplDecl class ObjCCategoryImplDecl : public ObjCImplDecl { + virtual void anchor(); + // Category name IdentifierInfo *Id; + // Category name location + SourceLocation CategoryNameLoc; + ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id, ObjCInterfaceDecl *classInterface, - SourceLocation nameLoc, SourceLocation atStartLoc) + SourceLocation nameLoc, SourceLocation atStartLoc, + SourceLocation CategoryNameLoc) : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc), - Id(Id) {} + Id(Id), CategoryNameLoc(CategoryNameLoc) {} public: static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, - SourceLocation atStartLoc); + SourceLocation atStartLoc, + SourceLocation CategoryNameLoc); + static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// getIdentifier - Get the identifier that names the category /// interface associated with this implementation. /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier() /// to mean something different. For example: - /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() - /// returns the class interface name, whereas - /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() + /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() + /// returns the class interface name, whereas + /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() /// returns the category name. IdentifierInfo *getIdentifier() const { return Id; @@ -1278,6 +1482,8 @@ public: ObjCCategoryDecl *getCategoryDecl() const; + SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } + /// getName - Get the name of identifier for the class interface associated /// with this implementation as a StringRef. // @@ -1306,10 +1512,12 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCategoryImplDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; -raw_ostream &operator<<(raw_ostream &OS, - const ObjCCategoryImplDecl *CID); +raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); /// ObjCImplementationDecl - Represents a class definition - this is where /// method definitions are specified. For example: @@ -1326,8 +1534,13 @@ raw_ostream &operator<<(raw_ostream &OS, /// specified, they need to be *identical* to the interface. /// class ObjCImplementationDecl : public ObjCImplDecl { + virtual void anchor(); /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; + /// @implementation may have private ivars. + SourceLocation IvarLBraceLoc; + SourceLocation IvarRBraceLoc; + /// Support for ivar initialization. /// IvarInitializers - The arguments used to initialize the ivars CXXCtorInitializer **IvarInitializers; @@ -1335,35 +1548,43 @@ class ObjCImplementationDecl : public ObjCImplDecl { /// true if class has a .cxx_[construct,destruct] method. bool HasCXXStructors : 1; - + /// true of class extension has at least one bitfield ivar. bool HasSynthBitfield : 1; - + ObjCImplementationDecl(DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, - SourceLocation nameLoc, SourceLocation atStartLoc) + SourceLocation nameLoc, SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), - SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), - HasCXXStructors(false), HasSynthBitfield(false) {} + SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), + IvarRBraceLoc(IvarRBraceLoc), + IvarInitializers(0), NumIvarInitializers(0), + HasCXXStructors(false), HasSynthBitfield(false){} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, SourceLocation nameLoc, - SourceLocation atStartLoc); - + SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()); + + static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// init_iterator - Iterates through the ivar initializer list. typedef CXXCtorInitializer **init_iterator; - + /// init_const_iterator - Iterates through the ivar initializer list. typedef CXXCtorInitializer * const * init_const_iterator; - + /// init_begin() - Retrieve an iterator to the first initializer. init_iterator init_begin() { return IvarInitializers; } /// begin() - Retrieve an iterator to the first initializer. init_const_iterator init_begin() const { return IvarInitializers; } - + /// init_end() - Retrieve an iterator past the last initializer. init_iterator init_end() { return IvarInitializers + NumIvarInitializers; @@ -1376,21 +1597,21 @@ public: unsigned getNumIvarInitializers() const { return NumIvarInitializers; } - + void setNumIvarInitializers(unsigned numNumIvarInitializers) { NumIvarInitializers = numNumIvarInitializers; } - + void setIvarInitializers(ASTContext &C, CXXCtorInitializer ** initializers, unsigned numInitializers); bool hasCXXStructors() const { return HasCXXStructors; } void setHasCXXStructors(bool val) { HasCXXStructors = val; } - + bool hasSynthBitfield() const { return HasSynthBitfield; } void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } - + /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. IdentifierInfo *getIdentifier() const { @@ -1428,6 +1649,11 @@ public: void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } + void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } + SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } + void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } + SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1450,12 +1676,12 @@ public: friend class ASTDeclWriter; }; -raw_ostream &operator<<(raw_ostream &OS, - const ObjCImplementationDecl *ID); +raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as @compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { + virtual void anchor(); /// Class that this is an alias of. ObjCInterfaceDecl *AliasedClass; @@ -1467,6 +1693,9 @@ public: SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl* aliasedClass); + static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } @@ -1482,6 +1711,7 @@ public: /// @property (assign, readwrite) int MyProperty; /// class ObjCPropertyDecl : public NamedDecl { + virtual void anchor(); public: enum PropertyAttributeKind { OBJC_PR_noattr = 0x00, @@ -1509,6 +1739,7 @@ public: enum PropertyControl { None, Required, Optional }; private: SourceLocation AtLoc; // location of @property + SourceLocation LParenLoc; // location of '(' starting attribute list or null. TypeSourceInfo *DeclType; unsigned PropertyAttributes : NumPropertyAttrsBits; unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; @@ -1523,9 +1754,11 @@ private: ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation AtLocation, TypeSourceInfo *T) - : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T), - PropertyAttributes(OBJC_PR_noattr), + SourceLocation AtLocation, SourceLocation LParenLocation, + TypeSourceInfo *T) + : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), + LParenLoc(LParenLocation), DeclType(T), + PropertyAttributes(OBJC_PR_noattr), PropertyAttributesAsWritten(OBJC_PR_noattr), PropertyImplementation(None), GetterName(Selector()), @@ -1535,11 +1768,18 @@ public: static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLocation, + SourceLocation LParenLocation, TypeSourceInfo *T, PropertyControl propControl = None); + + static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + TypeSourceInfo *getTypeSourceInfo() const { return DeclType; } QualType getType() const { return DeclType->getType(); } void setType(TypeSourceInfo *T) { DeclType = T; } @@ -1560,11 +1800,11 @@ public: OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_weak); } - + void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { PropertyAttributesAsWritten = PRVal; } - + void makeitReadWriteAttribute(void) { PropertyAttributes &= ~OBJC_PR_readonly; PropertyAttributes |= OBJC_PR_readwrite; @@ -1630,7 +1870,7 @@ public: return PropertyIvarDecl; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, getLocation()); } @@ -1655,7 +1895,7 @@ public: }; private: SourceLocation AtLoc; // location of @synthesize or @dynamic - + /// \brief For @synthesize, the location of the ivar, if it was written in /// the source code. /// @@ -1663,16 +1903,16 @@ private: /// @synthesize int a = b /// \endcode SourceLocation IvarLoc; - + /// Property declaration being implemented ObjCPropertyDecl *PropertyDecl; /// Null for @dynamic. Required for @synthesize. ObjCIvarDecl *PropertyIvarDecl; - + /// Null for @dynamic. Non-null if property must be copy-constructed in getter Expr *GetterCXXConstructor; - + /// Null for @dynamic. Non-null if property has assignment operator to call /// in Setter synthesis. Expr *SetterCXXAssignment; @@ -1683,7 +1923,7 @@ private: ObjCIvarDecl *ivarDecl, SourceLocation ivarLoc) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), + IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), GetterCXXConstructor(0), SetterCXXAssignment(0) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -1696,9 +1936,11 @@ public: ObjCIvarDecl *ivarDecl, SourceLocation ivarLoc); - virtual SourceRange getSourceRange() const; + static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceLocation getLocStart() const { return AtLoc; } + virtual SourceRange getSourceRange() const LLVM_READONLY; + + SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } ObjCPropertyDecl *getPropertyDecl() const { @@ -1714,13 +1956,13 @@ public: return PropertyIvarDecl; } SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; } - + void setPropertyIvarDecl(ObjCIvarDecl *Ivar, - SourceLocation IvarLoc) { - PropertyIvarDecl = Ivar; + SourceLocation IvarLoc) { + PropertyIvarDecl = Ivar; this->IvarLoc = IvarLoc; } - + Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } @@ -1734,11 +1976,11 @@ public: void setSetterCXXAssignment(Expr *setterCXXAssignment) { SetterCXXAssignment = setterCXXAssignment; } - + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCPropertyImplDecl *D) { return true; } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } - + friend class ASTDeclReader; }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h index 138e47d..36549ea 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h @@ -15,8 +15,10 @@ #define LLVM_CLANG_AST_DECLTEMPLATE_H #include "clang/AST/DeclCXX.h" +#include "clang/AST/Redeclarable.h" #include "clang/AST/TemplateBase.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Compiler.h" #include <limits> namespace clang { @@ -99,12 +101,12 @@ public: /// The first template parameter list in a declaration will have depth 0, /// the second template parameter list will have depth 1, etc. unsigned getDepth() const; - + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TemplateLoc, RAngleLoc); } }; @@ -116,7 +118,8 @@ class FixedSizeTemplateParameterList : public TemplateParameterList { NamedDecl *Params[N]; public: - FixedSizeTemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, + FixedSizeTemplateParameterList(SourceLocation TemplateLoc, + SourceLocation LAngleLoc, NamedDecl **Params, SourceLocation RAngleLoc) : TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) { } @@ -142,7 +145,7 @@ class TemplateArgumentList { : Arguments(Args, Owned), NumArguments(NumArgs) { } public: - /// \brief Type used to indicate that the template argument list itself is a + /// \brief Type used to indicate that the template argument list itself is a /// stack object. It does not own its template arguments. enum OnStackType { OnStack }; @@ -156,12 +159,12 @@ public: /// /// The template argument list does not own the template arguments /// provided. - explicit TemplateArgumentList(OnStackType, + explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args, unsigned NumArgs) : Arguments(Args, false), NumArguments(NumArgs) { } - - /// \brief Produces a shallow copy of the given template argument list. - /// + + /// \brief Produces a shallow copy of the given template argument list. + /// /// This operation assumes that the input argument list outlives it. /// This takes the list as a pointer to avoid looking like a copy /// constructor, since this really really isn't safe to use that @@ -197,6 +200,7 @@ public: /// parameters and a reference to the templated scoped declaration: the /// underlying AST node. class TemplateDecl : public NamedDecl { + virtual void anchor(); protected: // This is probably never used. TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -236,7 +240,7 @@ public: return K >= firstTemplate && K <= lastTemplate; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TemplateParams->getTemplateLoc(), TemplatedDecl->getSourceRange().getEnd()); } @@ -244,7 +248,7 @@ public: protected: NamedDecl *TemplatedDecl; TemplateParameterList* TemplateParams; - + public: /// \brief Initialize the underlying templated declaration and /// template parameters. @@ -298,9 +302,9 @@ public: const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; /// \brief The point at which this function template specialization was - /// first instantiated. + /// first instantiated. SourceLocation PointOfInstantiation; - + /// \brief Retrieve the template from which this function was specialized. FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } @@ -325,16 +329,16 @@ public: /// /// The point of instantiation may be an invalid source location if this /// function has yet to be instantiated. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; } - + /// \brief Set the (first) point of instantiation of this function template /// specialization. void setPointOfInstantiation(SourceLocation POI) { PointOfInstantiation = POI; } - + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, TemplateArguments->data(), TemplateArguments->size(), @@ -350,49 +354,49 @@ public: } }; -/// \brief Provides information a specialization of a member of a class -/// template, which may be a member function, static data member, or -/// member class. +/// \brief Provides information a specialization of a member of a class +/// template, which may be a member function, static data member, +/// member class or member enumeration. class MemberSpecializationInfo { // The member declaration from which this member was instantiated, and the // manner in which the instantiation occurred (in the lower two bits). llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK; - + // The point at which this member was first instantiated. SourceLocation PointOfInstantiation; - + public: - explicit + explicit MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK, SourceLocation POI = SourceLocation()) : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { - assert(TSK != TSK_Undeclared && + assert(TSK != TSK_Undeclared && "Cannot encode undeclared template specializations for members"); } - + /// \brief Retrieve the member declaration from which this member was /// instantiated. NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); } - + /// \brief Determine what kind of template specialization this is. TemplateSpecializationKind getTemplateSpecializationKind() const { return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1); } - + /// \brief Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { - assert(TSK != TSK_Undeclared && + assert(TSK != TSK_Undeclared && "Cannot encode undeclared template specializations for members"); MemberAndTSK.setInt(TSK - 1); } - - /// \brief Retrieve the first point of instantiation of this member. + + /// \brief Retrieve the first point of instantiation of this member. /// If the point of instantiation is an invalid location, then this member /// has not yet been instantiated. - SourceLocation getPointOfInstantiation() const { - return PointOfInstantiation; + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; } - + /// \brief Set the first point of instantiation. void setPointOfInstantiation(SourceLocation POI) { PointOfInstantiation = POI; @@ -414,14 +418,14 @@ class DependentFunctionTemplateSpecializationInfo { union { // Force sizeof to be a multiple of sizeof(void*) so that the // trailing data is aligned. - void *Aligner; + void *Aligner; struct { /// The number of potential template candidates. unsigned NumTemplates; /// The number of template arguments. - unsigned NumArgs; + unsigned NumArgs; } d; }; @@ -452,7 +456,7 @@ public: /// \brief Returns the explicit template arguments that were given. const TemplateArgumentLoc *getTemplateArgs() const { return reinterpret_cast<const TemplateArgumentLoc*>( - &getTemplates()[getNumTemplates()]); + &getTemplates()[getNumTemplates()]); } /// \brief Returns the number of explicit template arguments that were given. @@ -474,33 +478,28 @@ public: return AngleLocs.getEnd(); } }; - -/// Declaration of a redeclarable template. -class RedeclarableTemplateDecl : public TemplateDecl { - RedeclarableTemplateDecl *getPreviousDeclarationImpl() { - return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>(); +/// Declaration of a redeclarable template. +class RedeclarableTemplateDecl : public TemplateDecl, + public Redeclarable<RedeclarableTemplateDecl> +{ + typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base; + virtual RedeclarableTemplateDecl *getNextRedeclaration() { + return RedeclLink.getNext(); } - - RedeclarableTemplateDecl *getCanonicalDeclImpl(); - - void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev); - - RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + virtual RedeclarableTemplateDecl *getPreviousDeclImpl() { + return getPreviousDecl(); } - - void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(TD); + virtual RedeclarableTemplateDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); } protected: template <typename EntryType> struct SpecEntryTraits { typedef EntryType DeclType; - static DeclType *getMostRecentDeclaration(EntryType *D) { - return D->getMostRecentDeclaration(); + static DeclType *getMostRecentDecl(EntryType *D) { + return D->getMostRecentDecl(); } }; @@ -522,7 +521,7 @@ protected: SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {} DeclType *operator*() const { - return SETraits::getMostRecentDeclaration(&*SetIter); + return SETraits::getMostRecentDecl(&*SetIter); } DeclType *operator->() const { return **this; } @@ -562,15 +561,12 @@ protected: /// was explicitly specialized. llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> InstantiatedFromMember; - - /// \brief The latest declaration of this template. - RedeclarableTemplateDecl *Latest; }; - /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this template. - llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev; - + /// \brief Pointer to the common data shared by all declarations of this + /// template. + CommonBase *Common; + /// \brief Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. @@ -582,56 +578,18 @@ protected: RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(DK, DC, L, Name, Params, Decl), - CommonOrPrev((CommonBase*)0) { } + : TemplateDecl(DK, DC, L, Name, Params, Decl), Common() { } public: template <class decl_type> friend class RedeclarableTemplate; - RedeclarableTemplateDecl *getCanonicalDecl() { - return getCanonicalDeclImpl(); - } - - /// \brief Retrieve the previous declaration of this template, or - /// NULL if no such declaration exists. - RedeclarableTemplateDecl *getPreviousDeclaration() { - return getPreviousDeclarationImpl(); - } - - /// \brief Retrieve the previous declaration of this template, or - /// NULL if no such declaration exists. - const RedeclarableTemplateDecl *getPreviousDeclaration() const { - return - const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration(); - } - - /// \brief Retrieve the first declaration of this template, or itself - /// if this the first one. - RedeclarableTemplateDecl *getFirstDeclaration() { - return getCanonicalDecl(); - } - - /// \brief Retrieve the first declaration of this template, or itself - /// if this the first one. - const RedeclarableTemplateDecl *getFirstDeclaration() const { - return - const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration(); - } - - /// \brief Retrieve the most recent declaration of this template, or itself - /// if this the most recent one. - RedeclarableTemplateDecl *getMostRecentDeclaration() { - return getCommonPtr()->Latest; - } - - /// \brief Retrieve the most recent declaration of this template, or itself - /// if this the most recent one. - const RedeclarableTemplateDecl *getMostRecentDeclaration() const { - return - const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration(); + /// Retrieves the canonical declaration of this template. + RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); } + const RedeclarableTemplateDecl *getCanonicalDecl() const { + return getFirstDeclaration(); } - /// \brief Determines whether this template was a specialization of a + /// \brief Determines whether this template was a specialization of a /// member template. /// /// In the following example, the function template \c X<int>::f and the @@ -652,21 +610,64 @@ public: bool isMemberSpecialization() { return getCommonPtr()->InstantiatedFromMember.getInt(); } - + /// \brief Note that this member template is a specialization. void setMemberSpecialization() { assert(getCommonPtr()->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); getCommonPtr()->InstantiatedFromMember.setInt(true); } - - /// \brief Retrieve the previous declaration of this template, or - /// NULL if no such declaration exists. + + /// \brief Retrieve the member template from which this template was + /// instantiated, or NULL if this template was not instantiated from a + /// member template. + /// + /// A template is instantiated from a member template when the member + /// template itself is part of a class template (or member thereof). For + /// example, given + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> void f(T, U); + /// }; + /// + /// void test(X<int> x) { + /// x.f(1, 'a'); + /// }; + /// \endcode + /// + /// \c X<int>::f is a FunctionTemplateDecl that describes the function + /// template + /// + /// \code + /// template<typename U> void X<int>::f(int, U); + /// \endcode + /// + /// which was itself created during the instantiation of \c X<int>. Calling + /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will + /// retrieve the FunctionTemplateDecl for the original template "f" within + /// the class template \c X<T>, i.e., + /// + /// \code + /// template<typename T> + /// template<typename U> + /// void X<T>::f(T, U); + /// \endcode RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { - return getInstantiatedFromMemberTemplateImpl(); + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(TD); } - virtual RedeclarableTemplateDecl *getNextRedeclaration(); + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -678,107 +679,35 @@ public: return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; } + friend class ASTReader; friend class ASTDeclReader; friend class ASTDeclWriter; }; -template <class decl_type> -class RedeclarableTemplate { - RedeclarableTemplateDecl *thisDecl() { - return static_cast<decl_type*>(this); - } - -public: - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - decl_type *getPreviousDeclaration() { - return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl()); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - const decl_type *getPreviousDeclaration() const { - return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration(); - } - - /// \brief Set the previous declaration of this function template. - void setPreviousDeclaration(decl_type *Prev) { - thisDecl()->setPreviousDeclarationImpl(Prev); - } - - decl_type *getCanonicalDecl() { - return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl()); - } - - const decl_type *getCanonicalDecl() const { - return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl(); - } - - /// \brief Retrieve the member template that this template was instantiated - /// from. - /// - /// This routine will return non-NULL for member templates of - /// class templates. For example, given: - /// - /// \code - /// template <typename T> - /// struct X { - /// template <typename U> void f(); - /// template <typename U> struct A {}; - /// }; - /// \endcode - /// - /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a - /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will - /// return X<int>::f, a FunctionTemplateDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a - /// ClassTemplateDecl). - /// - /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent - /// is X<int>, also a CTSD) for which getSpecializedTemplate() will - /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again - /// X<int>) for which getInstantiatedFromMemberTemplate() will return - /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD). - /// - /// \returns NULL if this is not an instantiation of a member template. - decl_type *getInstantiatedFromMemberTemplate() { - return static_cast<decl_type*>( - thisDecl()->getInstantiatedFromMemberTemplateImpl()); - } - - void setInstantiatedFromMemberTemplate(decl_type *TD) { - thisDecl()->setInstantiatedFromMemberTemplateImpl(TD); - } -}; - template <> struct RedeclarableTemplateDecl:: SpecEntryTraits<FunctionTemplateSpecializationInfo> { typedef FunctionDecl DeclType; static DeclType * - getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) { - return I->Function->getMostRecentDeclaration(); + getMostRecentDecl(FunctionTemplateSpecializationInfo *I) { + return I->Function->getMostRecentDecl(); } }; /// Declaration of a template function. -class FunctionTemplateDecl : public RedeclarableTemplateDecl, - public RedeclarableTemplate<FunctionTemplateDecl> { +class FunctionTemplateDecl : public RedeclarableTemplateDecl { static void DeallocateCommon(void *Ptr); protected: - typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base; - /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { Common() : InjectedArgs(0) { } - + /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; - + /// \brief The set of "injected" template arguments used within this /// function template. /// @@ -813,7 +742,7 @@ protected: /// retrieved by an earlier call to findSpecialization(). void addSpecialization(FunctionTemplateSpecializationInfo* Info, void *InsertPos); - + public: /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { @@ -832,26 +761,31 @@ public: unsigned NumArgs, void *&InsertPos); FunctionTemplateDecl *getCanonicalDecl() { - return redeclarable_base::getCanonicalDecl(); + return cast<FunctionTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } const FunctionTemplateDecl *getCanonicalDecl() const { - return redeclarable_base::getCanonicalDecl(); + return cast<FunctionTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - FunctionTemplateDecl *getPreviousDeclaration() { - return redeclarable_base::getPreviousDeclaration(); + FunctionTemplateDecl *getPreviousDecl() { + return cast_or_null<FunctionTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - const FunctionTemplateDecl *getPreviousDeclaration() const { - return redeclarable_base::getPreviousDeclaration(); + const FunctionTemplateDecl *getPreviousDecl() const { + return cast_or_null<FunctionTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { - return redeclarable_base::getInstantiatedFromMemberTemplate(); + return cast_or_null<FunctionTemplateDecl>( + RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; @@ -866,13 +800,13 @@ public: /// \brief Retrieve the "injected" template arguments that correspond to the /// template parameters of this function template. - /// + /// /// Although the C++ standard has no notion of the "injected" template /// arguments for a function template, the notion is convenient when /// we need to perform substitutions inside the definition of a function - /// template. + /// template. std::pair<const TemplateArgument *, unsigned> getInjectedTemplateArgs(); - + /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -881,7 +815,7 @@ public: NamedDecl *Decl); /// \brief Create an empty function template node. - static FunctionTemplateDecl *Create(ASTContext &C, EmptyShell); + static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -966,7 +900,8 @@ public: unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); - static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty); + static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, + unsigned ID); /// \brief Whether this template type parameter was declared with /// the 'typename' keyword. If not, it was declared with the 'class' @@ -1003,21 +938,21 @@ public: DefaultArgument = 0; InheritedDefault = false; } - + /// \brief Set whether this template type parameter was declared with /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } /// \brief Retrieve the depth of the template parameter. unsigned getDepth() const; - + /// \brief Retrieve the index of the template parameter. unsigned getIndex() const; /// \brief Returns whether this is a parameter pack. bool isParameterPack() const; - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1038,18 +973,18 @@ class NonTypeTemplateParmDecl // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index // down here to save memory. - + /// \brief Whether this non-type template parameter is a parameter pack. bool ParameterPack; - - /// \brief Whether this non-type template parameter is an "expanded" + + /// \brief Whether this non-type template parameter is an "expanded" /// parameter pack, meaning that its type is a pack expansion and we /// already know the set of types that expansion expands to. bool ExpandedParameterPack; - + /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; - + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, @@ -1069,7 +1004,7 @@ class NonTypeTemplateParmDecl TypeSourceInfo **ExpandedTInfos); friend class ASTDeclReader; - + public: static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, @@ -1083,13 +1018,19 @@ public: const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos); + static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned NumExpandedTypes); + using TemplateParmPosition::getDepth; using TemplateParmPosition::setDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; /// \brief Determine whether this template parameter has a default /// argument. @@ -1135,7 +1076,7 @@ public: /// template<typename T, unsigned ...Dims> struct multi_array; /// \endcode bool isParameterPack() const { return ParameterPack; } - + /// \brief Whether this parameter is a non-type template parameter pack /// that has different types at different positions. /// @@ -1150,25 +1091,26 @@ public: /// struct Y { /* ... */ }; /// }; /// \endcode - /// + /// /// The parameter pack \c Values has a \c PackExpansionType as its type, /// which expands \c Types. When \c Types is supplied with template arguments - /// by instantiating \c X, the instantiation of \c Values becomes an - /// expanded parameter pack. For example, instantiating + /// by instantiating \c X, the instantiation of \c Values becomes an + /// expanded parameter pack. For example, instantiating /// \c X<int, unsigned int> results in \c Values being an expanded parameter /// pack with expansion types \c int and \c unsigned int. /// - /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions + /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions /// return the expansion types. bool isExpandedParameterPack() const { return ExpandedParameterPack; } - - /// \brief Retrieves the number of expansion types in an expanded parameter pack. + + /// \brief Retrieves the number of expansion types in an expanded parameter + /// pack. unsigned getNumExpansionTypes() const { assert(ExpandedParameterPack && "Not an expansion parameter pack"); return NumExpandedTypes; } - /// \brief Retrieve a particular expansion type within an expanded parameter + /// \brief Retrieve a particular expansion type within an expanded parameter /// pack. QualType getExpansionType(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); @@ -1176,7 +1118,7 @@ public: return QualType::getFromOpaquePtr(TypesAndInfos[2*I]); } - /// \brief Retrieve a particular expansion type source info within an + /// \brief Retrieve a particular expansion type source info within an /// expanded parameter pack. TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); @@ -1197,8 +1139,10 @@ public: /// @endcode /// A template template parameter is a TemplateDecl because it defines the /// name of a template and the template parameters allowable for substitution. -class TemplateTemplateParmDecl - : public TemplateDecl, protected TemplateParmPosition { +class TemplateTemplateParmDecl : public TemplateDecl, + protected TemplateParmPosition +{ + virtual void anchor(); /// DefaultArgument - The default template argument, if any. TemplateArgumentLoc DefaultArgument; @@ -1207,7 +1151,7 @@ class TemplateTemplateParmDecl /// \brief Whether this parameter is a parameter pack. bool ParameterPack; - + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) @@ -1223,6 +1167,9 @@ public: IdentifierInfo *Id, TemplateParameterList *Params); + static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::getIndex; @@ -1269,7 +1216,7 @@ public: DefaultArgumentWasInherited = false; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { SourceLocation End = getLocation(); if (hasDefaultArgument() && !defaultArgumentWasInherited()) End = getDefaultArgument().getSourceRange().getEnd(); @@ -1365,19 +1312,19 @@ public: unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl); static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, EmptyShell Empty); + CreateDeserialized(ASTContext &C, unsigned ID); virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; - ClassTemplateSpecializationDecl *getMostRecentDeclaration() { + ClassTemplateSpecializationDecl *getMostRecentDecl() { CXXRecordDecl *Recent - = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration()); + = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDecl()); if (!isa<ClassTemplateSpecializationDecl>(Recent)) { // FIXME: Does injected class name need to be in the redeclarations chain? - assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration()); - Recent = Recent->getPreviousDeclaration(); + assert(Recent->isInjectedClassName() && Recent->getPreviousDecl()); + Recent = Recent->getPreviousDecl(); } return cast<ClassTemplateSpecializationDecl>(Recent); } @@ -1525,7 +1472,7 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); @@ -1552,13 +1499,15 @@ public: static bool classof(const ClassTemplatePartialSpecializationDecl *) { return true; } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; class ClassTemplatePartialSpecializationDecl : public ClassTemplateSpecializationDecl { + virtual void anchor(); + /// \brief The list of template parameters TemplateParameterList* TemplateParams; @@ -1571,15 +1520,15 @@ class ClassTemplatePartialSpecializationDecl /// specialization was added to the set of partial specializations for /// its owning class template. unsigned SequenceNumber; - - /// \brief The class template partial specialization from which this + + /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. /// /// The boolean value will be true to indicate that this class template /// partial specialization was specialized at this level. llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> InstantiatedFromMember; - + ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, @@ -1592,7 +1541,7 @@ class ClassTemplatePartialSpecializationDecl unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl, unsigned SequenceNumber); - + ClassTemplatePartialSpecializationDecl() : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), TemplateParams(0), ArgsAsWritten(0), @@ -1601,7 +1550,7 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, TagKind TK,DeclContext *DC, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, @@ -1613,11 +1562,11 @@ public: unsigned SequenceNumber); static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, EmptyShell Empty); + CreateDeserialized(ASTContext &C, unsigned ID); - ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() { + ClassTemplatePartialSpecializationDecl *getMostRecentDecl() { return cast<ClassTemplatePartialSpecializationDecl>( - ClassTemplateSpecializationDecl::getMostRecentDeclaration()); + ClassTemplateSpecializationDecl::getMostRecentDecl()); } /// Get the list of template parameters @@ -1654,9 +1603,9 @@ public: /// \endcode /// /// In this example, the instantiation of \c Outer<float>::Inner<int*> will - /// end up instantiating the partial specialization - /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class - /// template partial specialization \c Outer<T>::Inner<U*>. Given + /// end up instantiating the partial specialization + /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class + /// template partial specialization \c Outer<T>::Inner<U*>. Given /// \c Outer<float>::Inner<U*>, this function would return /// \c Outer<T>::Inner<U*>. ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() { @@ -1664,15 +1613,15 @@ public: = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); return First->InstantiatedFromMember.getPointer(); } - + void setInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *PartialSpec) { ClassTemplatePartialSpecializationDecl *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); First->InstantiatedFromMember.setPointer(PartialSpec); } - - /// \brief Determines whether this class template partial specialization + + /// \brief Determines whether this class template partial specialization /// template was a specialization of a member partial specialization. /// /// In the following example, the member template partial specialization @@ -1693,7 +1642,7 @@ public: = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); return First->InstantiatedFromMember.getInt(); } - + /// \brief Note that this member template is a specialization. void setMemberSpecialization() { ClassTemplatePartialSpecializationDecl *First @@ -1711,7 +1660,7 @@ public: return cast<InjectedClassNameType>(getTypeForDecl()) ->getInjectedSpecializationType(); } - + // FIXME: Add Profile support! static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1728,18 +1677,15 @@ public: }; /// Declaration of a class template. -class ClassTemplateDecl : public RedeclarableTemplateDecl, - public RedeclarableTemplate<ClassTemplateDecl> { +class ClassTemplateDecl : public RedeclarableTemplateDecl { static void DeallocateCommon(void *Ptr); - -protected: - typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base; +protected: /// \brief Data that is common to all of the declarations of a given /// class template. struct Common : CommonBase { Common() : LazySpecializations() { } - + /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; @@ -1751,7 +1697,7 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; - + /// \brief If non-null, points to an array of specializations (including /// partial specializations) known ownly by their external declaration IDs. /// @@ -1762,7 +1708,7 @@ protected: /// \brief Load any lazily-loaded specializations from the external source. void LoadLazySpecializations(); - + /// \brief Retrieve the set of specializations of this class template. llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations(); @@ -1806,7 +1752,7 @@ public: ClassTemplateDecl *PrevDecl); /// Create an empty class template node. - static ClassTemplateDecl *Create(ASTContext &C, EmptyShell); + static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. @@ -1819,26 +1765,31 @@ public: void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); ClassTemplateDecl *getCanonicalDecl() { - return redeclarable_base::getCanonicalDecl(); + return cast<ClassTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } const ClassTemplateDecl *getCanonicalDecl() const { - return redeclarable_base::getCanonicalDecl(); + return cast<ClassTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } /// \brief Retrieve the previous declaration of this class template, or /// NULL if no such declaration exists. - ClassTemplateDecl *getPreviousDeclaration() { - return redeclarable_base::getPreviousDeclaration(); + ClassTemplateDecl *getPreviousDecl() { + return cast_or_null<ClassTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } /// \brief Retrieve the previous declaration of this class template, or /// NULL if no such declaration exists. - const ClassTemplateDecl *getPreviousDeclaration() const { - return redeclarable_base::getPreviousDeclaration(); + const ClassTemplateDecl *getPreviousDecl() const { + return cast_or_null<ClassTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } ClassTemplateDecl *getInstantiatedFromMemberTemplate() { - return redeclarable_base::getInstantiatedFromMemberTemplate(); + return cast_or_null<ClassTemplateDecl>( + RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } /// \brief Return the partial specialization with the provided arguments if it @@ -1860,7 +1811,7 @@ public: /// \brief Retrieve the partial specializations as an ordered list. void getPartialSpecializations( SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); - + /// \brief Find a class template partial specialization with the given /// type T. /// @@ -1870,7 +1821,7 @@ public: /// \returns the class template partial specialization that exactly matches /// the type \p T, or NULL if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); - + /// \brief Find a class template partial specialization which was instantiated /// from the given member partial specialization. /// @@ -1939,6 +1890,7 @@ public: /// NOTE: This class is not currently in use. All of the above /// will yield a FriendDecl, not a FriendTemplateDecl. class FriendTemplateDecl : public Decl { + virtual void anchor(); public: typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; @@ -1957,7 +1909,7 @@ private: FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, - unsigned NParams, + unsigned NParams, TemplateParameterList **Params, FriendUnion Friend, SourceLocation FriendLoc) @@ -1977,12 +1929,12 @@ private: public: static FriendTemplateDecl *Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc, - unsigned NParams, + unsigned NParams, TemplateParameterList **Params, FriendUnion Friend, SourceLocation FriendLoc); - static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty); + static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// If this friend declaration names a templated type (or /// a dependent member type of a templated type), return that @@ -2023,13 +1975,10 @@ public: /// Declaration of an alias template. For example: /// /// template <typename T> using V = std::map<T*, int, MyCompare<T>>; -class TypeAliasTemplateDecl : public RedeclarableTemplateDecl, - public RedeclarableTemplate<TypeAliasTemplateDecl> { +class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { static void DeallocateCommon(void *Ptr); protected: - typedef RedeclarableTemplate<TypeAliasTemplateDecl> redeclarable_base; - typedef CommonBase Common; TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -2050,29 +1999,34 @@ public: TypeAliasTemplateDecl *getCanonicalDecl() { - return redeclarable_base::getCanonicalDecl(); + return cast<TypeAliasTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } const TypeAliasTemplateDecl *getCanonicalDecl() const { - return redeclarable_base::getCanonicalDecl(); + return cast<TypeAliasTemplateDecl>( + RedeclarableTemplateDecl::getCanonicalDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - TypeAliasTemplateDecl *getPreviousDeclaration() { - return redeclarable_base::getPreviousDeclaration(); + TypeAliasTemplateDecl *getPreviousDecl() { + return cast_or_null<TypeAliasTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - const TypeAliasTemplateDecl *getPreviousDeclaration() const { - return redeclarable_base::getPreviousDeclaration(); + const TypeAliasTemplateDecl *getPreviousDecl() const { + return cast_or_null<TypeAliasTemplateDecl>( + RedeclarableTemplateDecl::getPreviousDecl()); } TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() { - return redeclarable_base::getInstantiatedFromMemberTemplate(); + return cast_or_null<TypeAliasTemplateDecl>( + RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - + /// \brief Create a function template node. static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -2081,7 +2035,7 @@ public: NamedDecl *Decl); /// \brief Create an empty alias template node. - static TypeAliasTemplateDecl *Create(ASTContext &C, EmptyShell); + static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2105,7 +2059,8 @@ public: /// CXXMethodDecl. Then during an instantiation of class A, it will be /// transformed into an actual function specialization. class ClassScopeFunctionSpecializationDecl : public Decl { -private: + virtual void anchor(); + ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD) : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), @@ -2126,11 +2081,9 @@ public: return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD); } - static ClassScopeFunctionSpecializationDecl *Create(ASTContext &Context, - EmptyShell Empty) { - return new (Context)ClassScopeFunctionSpecializationDecl(0, - SourceLocation(), 0); - } + static ClassScopeFunctionSpecializationDecl * + CreateDeserialized(ASTContext &Context, unsigned ID); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h index b5b6bd4..62654b8 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h @@ -30,12 +30,12 @@ class DeclVisitor { public: RetTy Visit(Decl *D) { switch (D->getKind()) { - default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); #define DECL(DERIVED, BASE) \ case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl); #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); } // If the implementation chooses not to implement a certain visit diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h index 2170f2b..6349d9c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h @@ -17,6 +17,7 @@ #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" #include "clang/Basic/PartialDiagnostic.h" +#include "llvm/Support/Compiler.h" namespace llvm { template <typename T> struct DenseMapInfo; @@ -510,8 +511,17 @@ public: /// getEndLoc - Retrieve the location of the last token. SourceLocation getEndLoc() const; /// getSourceRange - The range of the declaration name. - SourceRange getSourceRange() const { - return SourceRange(getBeginLoc(), getEndLoc()); + SourceRange getSourceRange() const LLVM_READONLY { + SourceLocation BeginLoc = getBeginLoc(); + SourceLocation EndLoc = getEndLoc(); + return SourceRange(BeginLoc, EndLoc.isValid() ? EndLoc : BeginLoc); + } + SourceLocation getLocStart() const LLVM_READONLY { + return getBeginLoc(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation EndLoc = getEndLoc(); + return EndLoc.isValid() ? EndLoc : getLocStart(); } }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h index 2bbe502..948dcb4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h @@ -177,7 +177,7 @@ inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const { assert(isDependentContext() && "cannot iterate dependent diagnostics of non-dependent context"); const DependentStoredDeclsMap *Map - = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr); + = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); if (!Map) return ddiag_iterator(); return ddiag_iterator(Map->FirstDiagnostic); diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h index 1242f4e..558bd00 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h @@ -21,12 +21,13 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/TemplateBase.h" -#include "clang/AST/UsuallyTinyPtrVector.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include <cctype> namespace clang { @@ -56,8 +57,8 @@ class Expr : public Stmt { protected: Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) - : Stmt(SC) + bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) + : Stmt(SC) { ExprBits.TypeDependent = TD; ExprBits.ValueDependent = VD; @@ -97,8 +98,8 @@ public: bool isValueDependent() const { return ExprBits.ValueDependent; } /// \brief Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { - ExprBits.ValueDependent = VD; + void setValueDependent(bool VD) { + ExprBits.ValueDependent = VD; if (VD) ExprBits.InstantiationDependent = true; } @@ -117,8 +118,8 @@ public: bool isTypeDependent() const { return ExprBits.TypeDependent; } /// \brief Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { - ExprBits.TypeDependent = TD; + void setTypeDependent(bool TD) { + ExprBits.TypeDependent = TD; if (TD) ExprBits.InstantiationDependent = true; } @@ -140,12 +141,12 @@ public: /// } /// \endcode /// - bool isInstantiationDependent() const { - return ExprBits.InstantiationDependent; + bool isInstantiationDependent() const { + return ExprBits.InstantiationDependent; } - + /// \brief Set whether this expression is instantiation-dependent or not. - void setInstantiationDependent(bool ID) { + void setInstantiationDependent(bool ID) { ExprBits.InstantiationDependent = ID; } @@ -163,8 +164,8 @@ public: /// /// The expressions \c args and \c static_cast<Types&&>(args) both /// contain parameter packs. - bool containsUnexpandedParameterPack() const { - return ExprBits.ContainsUnexpandedParameterPack; + bool containsUnexpandedParameterPack() const { + return ExprBits.ContainsUnexpandedParameterPack; } /// \brief Set the bit that describes whether this expression @@ -175,7 +176,7 @@ public: /// getExprLoc - Return the preferred location for the arrow when diagnosing /// a problem with a generic expression. - SourceLocation getExprLoc() const; + SourceLocation getExprLoc() const LLVM_READONLY; /// isUnusedResultAWarning - Return true if this immediate expression should /// be warned about if the result is unused. If so, fill in Loc and Ranges @@ -235,7 +236,6 @@ public: MLV_IncompleteType, MLV_ConstQualified, MLV_ArrayType, - MLV_NotBlockQualified, MLV_ReadonlyProperty, MLV_NoSetterProperty, MLV_MemberFunction, @@ -271,7 +271,6 @@ public: CM_RValue, // Not modifiable because it's an rvalue CM_Function, // Not modifiable because it's a function; C++ only CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext - CM_NotBlockQualified, // Not captured in the closure CM_NoSetterProperty,// Implicit assignment to ObjC property without setter CM_ConstQualified, CM_ArrayType, @@ -302,12 +301,12 @@ public: bool isPRValue() const { return Kind >= CL_Function; } bool isRValue() const { return Kind >= CL_XValue; } bool isModifiable() const { return getModifiable() == CM_Modifiable; } - + /// \brief Create a simple, modifiably lvalue static Classification makeSimpleLValue() { return Classification(CL_LValue, CM_Modifiable); } - + }; /// \brief Classify - Classify this expression according to the C++0x /// expression taxonomy. @@ -390,54 +389,79 @@ public: /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; - + + /// \brief Returns whether this expression has a placeholder type. + bool hasPlaceholderType() const { + return getType()->isPlaceholderType(); + } + + /// \brief Returns whether this expression has a specific placeholder type. + bool hasPlaceholderType(BuiltinType::Kind K) const { + assert(BuiltinType::isPlaceholderTypeKind(K)); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType())) + return BT->getKind() == K; + return false; + } + /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in /// C. bool isKnownToHaveBooleanValue() const; - + /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location /// of the invalid expression. + /// + /// Note: This does not perform the implicit conversions required by C++11 + /// [expr.const]p5. bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, SourceLocation *Loc = 0, bool isEvaluated = true) const; - bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const { - llvm::APSInt X; - return isIntegerConstantExpr(X, Ctx, Loc); - } - /// isConstantInitializer - Returns true if this expression is a constant - /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; + bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const; - /// EvalResult is a struct with detailed info about an evaluated expression. - struct EvalResult { - /// Val - This is the value the expression can be folded to. - APValue Val; + /// isCXX98IntegralConstantExpr - Return true if this expression is an + /// integral constant expression in C++98. Can only be used in C++. + bool isCXX98IntegralConstantExpr(ASTContext &Ctx) const; + + /// isCXX11ConstantExpr - Return true if this expression is a constant + /// expression in C++11. Can only be used in C++. + /// + /// Note: This does not perform the implicit conversions required by C++11 + /// [expr.const]p5. + bool isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result = 0, + SourceLocation *Loc = 0) const; + + /// isPotentialConstantExpr - Return true if this function's definition + /// might be usable in a constant expression in C++11, if it were marked + /// constexpr. Return false if the function can never produce a constant + /// expression, along with diagnostics describing why not. + static bool isPotentialConstantExpr(const FunctionDecl *FD, + llvm::SmallVectorImpl< + PartialDiagnosticAt> &Diags); + + /// isConstantInitializer - Returns true if this expression can be emitted to + /// IR as a constant, and thus can be used as a constant initializer in C. + bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; + /// EvalStatus is a struct with detailed info about an evaluation in progress. + struct EvalStatus { /// HasSideEffects - Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. bool HasSideEffects; - /// Diag - If the expression is unfoldable, then Diag contains a note - /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret - /// position for the error, and DiagExpr is the expression that caused - /// the error. - /// If the expression is foldable, but not an integer constant expression, - /// Diag contains a note diagnostic that describes why it isn't an integer - /// constant expression. If the expression *is* an integer constant - /// expression, then Diag will be zero. - unsigned Diag; - const Expr *DiagExpr; - SourceLocation DiagLoc; + /// Diag - If this is non-null, it will be filled in with a stack of notes + /// indicating why evaluation failed (or why it failed to produce a constant + /// expression). + /// If the expression is unfoldable, the notes will indicate why it's not + /// foldable. If the expression is foldable, but not a constant expression, + /// the notes will describes why it isn't a constant expression. If the + /// expression *is* a constant expression, no notes will be produced. + llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag; - EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} + EvalStatus() : HasSideEffects(false), Diag(0) {} - // isGlobalLValue - Return true if the evaluated lvalue expression - // is global. - bool isGlobalLValue() const; // hasSideEffects - Return true if the evaluated expression has // side effects. bool hasSideEffects() const { @@ -445,11 +469,23 @@ public: } }; - /// Evaluate - Return true if this is a constant which we can fold using - /// any crazy technique (that has nothing to do with language standards) that - /// we want to. If this function returns true, it returns the folded constant - /// in Result. - bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const; + /// EvalResult is a struct with detailed info about an evaluated expression. + struct EvalResult : EvalStatus { + /// Val - This is the value the expression can be folded to. + APValue Val; + + // isGlobalLValue - Return true if the evaluated lvalue expression + // is global. + bool isGlobalLValue() const; + }; + + /// EvaluateAsRValue - Return true if this is a constant which we can fold to + /// an rvalue using any crazy technique (that has nothing to do with language + /// standards) that we want to, even if the expression has side-effects. If + /// this function returns true, it returns the folded constant in Result. If + /// the expression is a glvalue, an lvalue-to-rvalue conversion will be + /// applied. + bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we we can fold and convert to a boolean condition using @@ -457,30 +493,43 @@ public: /// side-effects. bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; + enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects }; + /// EvaluateAsInt - Return true if this is a constant which we can fold and - /// convert to an integer using any crazy technique that we want to. - bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx) const; + /// convert to an integer, using any crazy technique that we want to. + bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; - /// isEvaluatable - Call Evaluate to see if this expression can be constant - /// folded, but discard the result. + /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be + /// constant folded without side-effects, but discard the result. bool isEvaluatable(const ASTContext &Ctx) const; /// HasSideEffects - This routine returns true for all those expressions - /// which must be evaluated each time and must not be optimized away + /// which must be evaluated each time and must not be optimized away /// or evaluated at compile time. Example is a function call, volatile /// variable read. bool HasSideEffects(const ASTContext &Ctx) const; + + /// \brief Determine whether this expression involves a call to any function + /// that is not trivial. + bool hasNonTrivialCall(ASTContext &Ctx); - /// EvaluateKnownConstInt - Call Evaluate and return the folded integer. This - /// must be called on an expression that constant folds to an integer. + /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded + /// integer. This must be called on an expression that constant folds to an + /// integer. llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const; - /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue - /// with link time known address. + /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an + /// lvalue with link time known address, with no side-effects. bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const; - /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. - bool EvaluateAsAnyLValue(EvalResult &Result, const ASTContext &Ctx) const; + /// EvaluateAsInitializer - Evaluate an expression as if it were the + /// initializer of the given declaration. Returns true if the initializer + /// can be folded to a constant, and produces any relevant notes. In C++11, + /// notes will be produced if the expression is not a constant expression. + bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, + const VarDecl *VD, + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const; /// \brief Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). @@ -503,16 +552,16 @@ public: enum NullPointerConstantValueDependence { /// \brief Specifies that the expression should never be value-dependent. NPC_NeverValueDependent = 0, - + /// \brief Specifies that a value-dependent expression of integral or /// dependent type should be considered a null pointer constant. NPC_ValueDependentIsNull, - + /// \brief Specifies that a value-dependent expression should be considered /// to never be a null pointer constant. NPC_ValueDependentIsNotNull }; - + /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to /// a Null pointer constant. The return value can further distinguish the /// kind of NULL pointer constant that was detected. @@ -544,60 +593,62 @@ public: /// IgnoreImpCasts - Skip past any implicit casts which might /// surround this expression. Only skips ImplicitCastExprs. - Expr *IgnoreImpCasts(); + Expr *IgnoreImpCasts() LLVM_READONLY; /// IgnoreImplicit - Skip past any implicit AST nodes which might /// surround this expression. - Expr *IgnoreImplicit() { return cast<Expr>(Stmt::IgnoreImplicit()); } + Expr *IgnoreImplicit() LLVM_READONLY { + return cast<Expr>(Stmt::IgnoreImplicit()); + } /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. /// Otherwise, the method returns the current Expr. - Expr *IgnoreParens(); + Expr *IgnoreParens() LLVM_READONLY; /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr /// or CastExprs, returning their operand. - Expr *IgnoreParenCasts(); + Expr *IgnoreParenCasts() LLVM_READONLY; - /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any - /// ParenExpr or ImplicitCastExprs, returning their operand. - Expr *IgnoreParenImpCasts(); + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off + /// any ParenExpr or ImplicitCastExprs, returning their operand. + Expr *IgnoreParenImpCasts() LLVM_READONLY; /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a /// call to a conversion operator, return the argument. - Expr *IgnoreConversionOperator(); + Expr *IgnoreConversionOperator() LLVM_READONLY; - const Expr *IgnoreConversionOperator() const { + const Expr *IgnoreConversionOperator() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreConversionOperator(); } - const Expr *IgnoreParenImpCasts() const { + const Expr *IgnoreParenImpCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenImpCasts(); } - + /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and /// CastExprs that represent lvalue casts, returning their operand. - Expr *IgnoreParenLValueCasts(); - - const Expr *IgnoreParenLValueCasts() const { + Expr *IgnoreParenLValueCasts() LLVM_READONLY; + + const Expr *IgnoreParenLValueCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenLValueCasts(); } /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. - Expr *IgnoreParenNoopCasts(ASTContext &Ctx); + Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; /// \brief Determine whether this expression is a default function argument. /// /// Default arguments are implicitly generated in the abstract syntax tree - /// by semantic analysis for function calls, object constructions, etc. in + /// by semantic analysis for function calls, object constructions, etc. in /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes; /// this routine also looks through any implicit casts to determine whether /// the expression is a default argument. bool isDefaultArgument() const; - + /// \brief Determine whether the result of this expression is a /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; @@ -605,21 +656,20 @@ public: /// \brief Whether this expression is an implicit reference to 'this' in C++. bool isImplicitCXXThis() const; - const Expr *IgnoreImpCasts() const { + const Expr *IgnoreImpCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreImpCasts(); } - const Expr *IgnoreParens() const { + const Expr *IgnoreParens() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParens(); } - const Expr *IgnoreParenCasts() const { + const Expr *IgnoreParenCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenCasts(); } - const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const { + const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); } - static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs); - static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs); + static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs); static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && @@ -642,15 +692,18 @@ class OpaqueValueExpr : public Expr { friend class ASTStmtReader; Expr *SourceExpr; SourceLocation Loc; - + public: - OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, - ExprObjectKind OK = OK_Ordinary) + OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, + ExprObjectKind OK = OK_Ordinary, + Expr *SourceExpr = 0) : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), T->isDependentType(), + T->isDependentType(), + T->isDependentType() || + (SourceExpr && SourceExpr->isValueDependent()), T->isInstantiationDependentType(), - false), - SourceExpr(0), Loc(Loc) { + false), + SourceExpr(SourceExpr), Loc(Loc) { } /// Given an expression which invokes a copy constructor --- i.e. a @@ -663,12 +716,12 @@ public: /// \brief Retrieve the location of this expression. SourceLocation getLocation() const { return Loc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { if (SourceExpr) return SourceExpr->getSourceRange(); return Loc; } - SourceLocation getExprLoc() const { + SourceLocation getExprLoc() const LLVM_READONLY { if (SourceExpr) return SourceExpr->getExprLoc(); return Loc; } @@ -684,7 +737,6 @@ public: /// expression which binds the opaque value expression in the first /// place. Expr *getSourceExpr() const { return SourceExpr; } - void setSourceExpr(Expr *e) { SourceExpr = e; } static bool classof(const Stmt *T) { return T->getStmtClass() == OpaqueValueExprClass; @@ -709,9 +761,12 @@ public: /// Specifies when this declaration reference expression has a record of /// a NamedDecl (different from the referenced ValueDecl) which was found /// during name lookup and/or overload resolution. -/// DeclRefExprBits.HasExplicitTemplateArgs: +/// DeclRefExprBits.HasTemplateKWAndArgsInfo: /// Specifies when this declaration reference expression has an explicit -/// C++ template argument list. +/// C++ template keyword and/or template argument list. +/// DeclRefExprBits.RefersToEnclosingLocal +/// Specifies when this declaration reference expression (validly) +/// refers to a local variable from a different function. class DeclRefExpr : public Expr { /// \brief The declaration that we are referencing. ValueDecl *D; @@ -753,8 +808,11 @@ class DeclRefExpr : public Expr { return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl(); } - DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, - ValueDecl *D, const DeclarationNameInfo &NameInfo, + DeclRefExpr(ASTContext &Ctx, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + ValueDecl *D, bool refersToEnclosingLocal, + const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); @@ -765,23 +823,27 @@ class DeclRefExpr : public Expr { /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. - void computeDependence(); + void computeDependence(ASTContext &C); public: - DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L, + DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T, + ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), D(D), Loc(L), DNLoc(LocInfo) { DeclRefExprBits.HasQualifier = 0; - DeclRefExprBits.HasExplicitTemplateArgs = 0; + DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; DeclRefExprBits.HasFoundDecl = 0; DeclRefExprBits.HadMultipleCandidates = 0; - computeDependence(); + DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal; + computeDependence(D->getASTContext()); } static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool isEnclosingLocal, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD = 0, @@ -789,7 +851,9 @@ public: static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool isEnclosingLocal, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, NamedDecl *FoundD = 0, @@ -799,7 +863,7 @@ public: static DeclRefExpr *CreateEmpty(ASTContext &Context, bool HasQualifier, bool HasFoundDecl, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); ValueDecl *getDecl() { return D; } @@ -812,7 +876,9 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. @@ -851,25 +917,65 @@ public: return hasFoundDecl() ? getInternalFoundDecl() : D; } - /// \brief Determines whether this declaration reference was followed by an - /// explict template argument list. - bool hasExplicitTemplateArgs() const { - return DeclRefExprBits.HasExplicitTemplateArgs; + bool hasTemplateKWAndArgsInfo() const { + return DeclRefExprBits.HasTemplateKWAndArgsInfo; } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!hasTemplateKWAndArgsInfo()) + return 0; + if (hasFoundDecl()) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( &getInternalFoundDecl() + 1); if (hasQualifier()) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( &getInternalQualifierLoc() + 1); - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); + } + + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo(); + } + + /// \brief Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// \brief Determines whether the name in this declaration reference + /// was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// \brief Determines whether this declaration reference was followed by an + /// explicit template argument list. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *getTemplateKWAndArgsInfo(); } /// \brief Retrieve the explicit template argument list that followed the @@ -881,7 +987,7 @@ public: /// \brief Retrieves the optional explicit template arguments. /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getExplicitTemplateArgsOpt() const { + const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } @@ -893,15 +999,6 @@ public: getExplicitTemplateArgs().copyInto(List); } - /// \brief Retrieve the location of the left angle bracket following the - /// member name ('<'), if any. - SourceLocation getLAngleLoc() const { - if (!hasExplicitTemplateArgs()) - return SourceLocation(); - - return getExplicitTemplateArgs().LAngleLoc; - } - /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { @@ -920,15 +1017,6 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { - if (!hasExplicitTemplateArgs()) - return SourceLocation(); - - return getExplicitTemplateArgs().RAngleLoc; - } - /// \brief Returns true if this expression refers to a function that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { @@ -941,6 +1029,12 @@ public: DeclRefExprBits.HadMultipleCandidates = V; } + /// Does this DeclRefExpr refer to a local declaration from an + /// enclosing function scope? + bool refersToEnclosingLocal() const { + return DeclRefExprBits.RefersToEnclosingLocal; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -971,7 +1065,7 @@ private: public: PredefinedExpr(SourceLocation l, QualType type, IdentType IT) : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, - type->isDependentType(), type->isDependentType(), + type->isDependentType(), type->isDependentType(), type->isInstantiationDependentType(), /*ContainsUnexpandedParameterPack=*/false), Loc(l), Type(IT) {} @@ -988,7 +1082,7 @@ public: static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == PredefinedExprClass; @@ -1008,11 +1102,11 @@ public: /// the APFloat/APInt values will never get freed. APNumericStorage uses /// ASTContext's allocator for memory allocation. class APNumericStorage { - unsigned BitWidth; union { uint64_t VAL; ///< Used to store the <= 64 bits integer value. uint64_t *pVal; ///< Used to store the >64 bits integer value. }; + unsigned BitWidth; bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } @@ -1020,7 +1114,7 @@ class APNumericStorage { APNumericStorage& operator=(const APNumericStorage&); // do not implement protected: - APNumericStorage() : BitWidth(0), VAL(0) { } + APNumericStorage() : VAL(0), BitWidth(0) { } llvm::APInt getIntValue() const { unsigned NumWords = llvm::APInt::getNumWords(BitWidth); @@ -1032,22 +1126,23 @@ protected: void setIntValue(ASTContext &C, const llvm::APInt &Val); }; -class APIntStorage : public APNumericStorage { -public: - llvm::APInt getValue() const { return getIntValue(); } +class APIntStorage : private APNumericStorage { +public: + llvm::APInt getValue() const { return getIntValue(); } void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } }; -class APFloatStorage : public APNumericStorage { -public: - llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); } +class APFloatStorage : private APNumericStorage { +public: + llvm::APFloat getValue(bool IsIEEE) const { + return llvm::APFloat(getIntValue(), IsIEEE); + } void setValue(ASTContext &C, const llvm::APFloat &Val) { setIntValue(C, Val.bitcastToAPInt()); } }; -class IntegerLiteral : public Expr { - APIntStorage Num; +class IntegerLiteral : public Expr, public APIntStorage { SourceLocation Loc; /// \brief Construct an empty integer literal. @@ -1077,13 +1172,11 @@ public: /// \brief Returns a new empty integer literal. static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); - llvm::APInt getValue() const { return Num.getValue(); } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } - void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); } void setLocation(SourceLocation Location) { Loc = Location; } static bool classof(const Stmt *T) { @@ -1107,28 +1200,30 @@ public: private: unsigned Value; SourceLocation Loc; - unsigned Kind : 2; public: // type should be IntTy CharacterLiteral(unsigned value, CharacterKind kind, QualType type, SourceLocation l) : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, false, false), - Value(value), Loc(l), Kind(kind) { + Value(value), Loc(l) { + CharacterLiteralBits.Kind = kind; } /// \brief Construct an empty character literal. CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } SourceLocation getLocation() const { return Loc; } - CharacterKind getKind() const { return static_cast<CharacterKind>(Kind); } + CharacterKind getKind() const { + return static_cast<CharacterKind>(CharacterLiteralBits.Kind); + } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } unsigned getValue() const { return Value; } void setLocation(SourceLocation Location) { Loc = Location; } - void setKind(CharacterKind kind) { Kind = kind; } + void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; } void setValue(unsigned Val) { Value = Val; } static bool classof(const Stmt *T) { @@ -1140,35 +1235,41 @@ public: child_range children() { return child_range(); } }; -class FloatingLiteral : public Expr { - APFloatStorage Num; - bool IsExact : 1; +class FloatingLiteral : public Expr, private APFloatStorage { SourceLocation Loc; FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, - false, false), - IsExact(isexact), Loc(L) { + false, false), Loc(L) { + FloatingLiteralBits.IsIEEE = + &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + FloatingLiteralBits.IsExact = isexact; setValue(C, V); } /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty), IsExact(false) { } + explicit FloatingLiteral(ASTContext &C, EmptyShell Empty) + : Expr(FloatingLiteralClass, Empty) { + FloatingLiteralBits.IsIEEE = + &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + FloatingLiteralBits.IsExact = false; + } public: static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L); static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); - llvm::APFloat getValue() const { return Num.getValue(); } + llvm::APFloat getValue() const { + return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE); + } void setValue(ASTContext &C, const llvm::APFloat &Val) { - Num.setValue(C, Val); + APFloatStorage::setValue(C, Val); } - bool isExact() const { return IsExact; } - void setExact(bool E) { IsExact = E; } + bool isExact() const { return FloatingLiteralBits.IsExact; } + void setExact(bool E) { FloatingLiteralBits.IsExact = E; } /// getValueAsApproximateDouble - This returns the value as an inaccurate /// double. Note that this may cause loss of precision, but is useful for @@ -1178,7 +1279,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; @@ -1210,7 +1311,7 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const { return Val->getSourceRange(); } + SourceRange getSourceRange() const LLVM_READONLY { return Val->getSourceRange(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ImaginaryLiteralClass; } @@ -1249,17 +1350,24 @@ public: private: friend class ASTStmtReader; - const char *StrData; - unsigned ByteLength; - unsigned NumConcatenated; + union { + const char *asChar; + const uint16_t *asUInt16; + const uint32_t *asUInt32; + } StrData; + unsigned Length; + unsigned CharByteWidth : 4; unsigned Kind : 3; - bool IsPascal : 1; + unsigned IsPascal : 1; + unsigned NumConcatenated; SourceLocation TokLocs[1]; StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, false) {} + static int mapCharByteWidth(TargetInfo const &target,StringKind k); + public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. @@ -1278,15 +1386,46 @@ public: static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); StringRef getString() const { - return StringRef(StrData, ByteLength); - } - - unsigned getByteLength() const { return ByteLength; } + assert(CharByteWidth==1 + && "This function is used in places that assume strings use char"); + return StringRef(StrData.asChar, getByteLength()); + } + + /// Allow clients that need the byte representation, such as ASTWriterStmt + /// ::VisitStringLiteral(), access. + StringRef getBytes() const { + // FIXME: StringRef may not be the right type to use as a result for this. + if (CharByteWidth == 1) + return StringRef(StrData.asChar, getByteLength()); + if (CharByteWidth == 4) + return StringRef(reinterpret_cast<const char*>(StrData.asUInt32), + getByteLength()); + assert(CharByteWidth == 2 && "unsupported CharByteWidth"); + return StringRef(reinterpret_cast<const char*>(StrData.asUInt16), + getByteLength()); + } + + uint32_t getCodeUnit(size_t i) const { + assert(i < Length && "out of bounds access"); + if (CharByteWidth == 1) + return static_cast<unsigned char>(StrData.asChar[i]); + if (CharByteWidth == 4) + return StrData.asUInt32[i]; + assert(CharByteWidth == 2 && "unsupported CharByteWidth"); + return StrData.asUInt16[i]; + } + + unsigned getByteLength() const { return CharByteWidth*Length; } + unsigned getLength() const { return Length; } + unsigned getCharByteWidth() const { return CharByteWidth; } /// \brief Sets the string data to the given string data. - void setString(ASTContext &C, StringRef Str); + void setString(ASTContext &C, StringRef Str, + StringKind Kind, bool IsPascal); StringKind getKind() const { return static_cast<StringKind>(Kind); } + + bool isAscii() const { return Kind == Ascii; } bool isWide() const { return Kind == Wide; } bool isUTF8() const { return Kind == UTF8; } @@ -1301,6 +1440,7 @@ public: return true; return false; } + /// getNumConcatenated - Get the number of string literal tokens that were /// concatenated in translation phase #6 to form this string literal. unsigned getNumConcatenated() const { return NumConcatenated; } @@ -1313,7 +1453,7 @@ public: assert(TokNum < NumConcatenated && "Invalid tok number"); TokLocs[TokNum] = L; } - + /// getLocationOfByte - Return a source location that points to the specified /// byte of this string literal. /// @@ -1329,7 +1469,7 @@ public: tokloc_iterator tokloc_begin() const { return TokLocs; } tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); } static bool classof(const Stmt *T) { @@ -1363,7 +1503,7 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const { return SourceRange(L, R); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(L, R); } /// \brief Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } @@ -1408,7 +1548,7 @@ public: : Expr(UnaryOperatorClass, type, VK, OK, input->isTypeDependent() || type->isDependentType(), input->isValueDependent(), - (input->isInstantiationDependent() || + (input->isInstantiationDependent() || type->isInstantiationDependentType()), input->containsUnexpandedParameterPack()), Opc(opc), Loc(l), Val(input) {} @@ -1439,12 +1579,26 @@ public: bool isPrefix() const { return isPrefix(getOpcode()); } bool isPostfix() const { return isPostfix(getOpcode()); } + + static bool isIncrementOp(Opcode Op) { + return Op == UO_PreInc || Op == UO_PostInc; + } bool isIncrementOp() const { - return Opc == UO_PreInc || Opc == UO_PostInc; + return isIncrementOp(getOpcode()); + } + + static bool isDecrementOp(Opcode Op) { + return Op == UO_PreDec || Op == UO_PostDec; + } + bool isDecrementOp() const { + return isDecrementOp(getOpcode()); } + + static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; } bool isIncrementDecrementOp() const { - return Opc <= UO_PreDec; + return isIncrementDecrementOp(getOpcode()); } + static bool isArithmeticOp(Opcode Op) { return Op >= UO_Plus && Op <= UO_LNot; } @@ -1462,13 +1616,13 @@ public: /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { if (isPostfix()) return SourceRange(Val->getLocStart(), Loc); else return SourceRange(Loc, Val->getLocEnd()); } - SourceLocation getExprLoc() const { return Loc; } + SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryOperatorClass; @@ -1484,14 +1638,14 @@ public: /// @code /// struct S { /// float f; -/// double d; +/// double d; /// }; /// struct T { /// int i; /// struct S s[10]; /// }; /// @endcode -/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). +/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). class OffsetOfExpr : public Expr { public: @@ -1513,48 +1667,48 @@ public: private: enum { MaskBits = 2, Mask = 0x03 }; - + /// \brief The source range that covers this part of the designator. SourceRange Range; - + /// \brief The data describing the designator, which comes in three /// different forms, depending on the lower two bits. - /// - An unsigned index into the array of Expr*'s stored after this node + /// - An unsigned index into the array of Expr*'s stored after this node /// in memory, for [constant-expression] designators. /// - A FieldDecl*, for references to a known field. /// - An IdentifierInfo*, for references to a field with a given name /// when the class type is dependent. - /// - A CXXBaseSpecifier*, for references that look at a field in a + /// - A CXXBaseSpecifier*, for references that look at a field in a /// base class. uintptr_t Data; - + public: /// \brief Create an offsetof node that refers to an array element. - OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, + OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, SourceLocation RBracketLoc) : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { } - + /// \brief Create an offsetof node that refers to a field. - OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, + OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { } - + /// \brief Create an offsetof node that refers to an identifier. OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { } /// \brief Create an offsetof node that refers into a C++ base class. explicit OffsetOfNode(const CXXBaseSpecifier *Base) : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} - + /// \brief Determine what kind of offsetof node this is. - Kind getKind() const { + Kind getKind() const { return static_cast<Kind>(Data & Mask); } - + /// \brief For an array element node, returns the index into the array /// of expressions. unsigned getArrayExprIndex() const { @@ -1567,28 +1721,28 @@ public: assert(getKind() == Field); return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); } - + /// \brief For a field or identifier offsetof node, returns the name of /// the field. IdentifierInfo *getFieldName() const; - + /// \brief For a base class node, returns the base specifier. CXXBaseSpecifier *getBase() const { assert(getKind() == Base); - return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); + return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); } - + /// \brief Retrieve the source range that covers this offsetof node. /// /// For an array element node, the source range contains the locations of /// the square brackets. For a field or identifier node, the source range - /// contains the location of the period (if there is one) and the + /// contains the location of the period (if there is one) and the /// identifier. - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } }; private: - + SourceLocation OperatorLoc, RParenLoc; // Base type; TypeSourceInfo *TSInfo; @@ -1596,26 +1750,26 @@ private: unsigned NumComps; // Number of sub-expressions (i.e. array subscript expressions). unsigned NumExprs; - - OffsetOfExpr(ASTContext &C, QualType type, + + OffsetOfExpr(ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, + OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc); explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) : Expr(OffsetOfExprClass, EmptyShell()), - TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} + TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} public: - - static OffsetOfExpr *Create(ASTContext &C, QualType type, - SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, + + static OffsetOfExpr *Create(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc); - static OffsetOfExpr *CreateEmpty(ASTContext &C, + static OffsetOfExpr *CreateEmpty(ASTContext &C, unsigned NumComps, unsigned NumExprs); /// getOperatorLoc - Return the location of the operator. @@ -1625,14 +1779,14 @@ public: /// \brief Return the location of the right parentheses. SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation R) { RParenLoc = R; } - + TypeSourceInfo *getTypeSourceInfo() const { return TSInfo; } void setTypeSourceInfo(TypeSourceInfo *tsi) { TSInfo = tsi; } - + const OffsetOfNode &getComponent(unsigned Idx) const { assert(Idx < NumComps && "Subscript out of range"); return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx]; @@ -1642,7 +1796,7 @@ public: assert(Idx < NumComps && "Subscript out of range"); reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; } - + unsigned getNumComponents() const { return NumComps; } @@ -1661,12 +1815,12 @@ public: reinterpret_cast<Expr **>( reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; } - + unsigned getNumExpressions() const { return NumExprs; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(OperatorLoc, RParenLoc); } @@ -1689,8 +1843,6 @@ public: /// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and /// vec_step (OpenCL 1.1 6.11.12). class UnaryExprOrTypeTraitExpr : public Expr { - unsigned Kind : 2; - bool isType : 1; // true if operand is a type, false if an expression union { TypeSourceInfo *Ty; Stmt *Ex; @@ -1707,7 +1859,9 @@ public: TInfo->getType()->isDependentType(), TInfo->getType()->isInstantiationDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), - Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = true; Argument.Ty = TInfo; } @@ -1720,7 +1874,9 @@ public: E->isTypeDependent(), E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), - Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = false; Argument.Ex = E; } @@ -1729,11 +1885,11 @@ public: : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } UnaryExprOrTypeTrait getKind() const { - return static_cast<UnaryExprOrTypeTrait>(Kind); + return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind); } - void setKind(UnaryExprOrTypeTrait K) { Kind = K; } + void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;} - bool isArgumentType() const { return isType; } + bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; } QualType getArgumentType() const { return getArgumentTypeInfo()->getType(); } @@ -1749,10 +1905,13 @@ public: return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); } - void setArgument(Expr *E) { Argument.Ex = E; isType = false; } + void setArgument(Expr *E) { + Argument.Ex = E; + UnaryExprOrTypeTraitExprBits.IsType = false; + } void setArgument(TypeSourceInfo *TInfo) { Argument.Ty = TInfo; - isType = true; + UnaryExprOrTypeTraitExprBits.IsType = true; } /// Gets the argument type, or the type of the argument expression, whichever @@ -1767,7 +1926,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(OpLoc, RParenLoc); } @@ -1842,14 +2001,14 @@ public: return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLHS()->getLocStart(), RBracketLoc); } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - SourceLocation getExprLoc() const { return getBase()->getExprLoc(); } + SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ArraySubscriptExprClass; @@ -1927,7 +2086,10 @@ public: Expr **getArgs() { return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); } - + const Expr *const *getArgs() const { + return const_cast<CallExpr*>(this)->getArgs(); + } + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -1969,7 +2131,7 @@ public: /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. - unsigned isBuiltinCall(const ASTContext &Context) const; + unsigned isBuiltinCall() const; /// getCallReturnType - Get the return type of the call expr. This is not /// always the type of the expr itself, if the return type is a reference @@ -1979,7 +2141,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCallExprConstant && @@ -2016,13 +2180,13 @@ class MemberExpr : public Expr { /// In X.F, this is the decl referenced by F. ValueDecl *MemberDecl; - /// MemberLoc - This is the location of the member name. - SourceLocation MemberLoc; - /// MemberDNLoc - Provides source/type location info for the /// declaration name embedded in MemberDecl. DeclarationNameLoc MemberDNLoc; + /// MemberLoc - This is the location of the member name. + SourceLocation MemberLoc; + /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow : 1; @@ -2032,12 +2196,14 @@ class MemberExpr : public Expr { /// structure is allocated immediately after the MemberExpr. bool HasQualifierOrFoundDecl : 1; - /// \brief True if this member expression specified a template argument list - /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList - /// structure (and its TemplateArguments) are allocated immediately after - /// the MemberExpr or, if the member expression also has a qualifier, after - /// the MemberNameQualifier structure. - bool HasExplicitTemplateArgumentList : 1; + /// \brief True if this member expression specified a template keyword + /// and/or a template argument list explicitly, e.g., x->f<int>, + /// x->template f, x->template f<int>. + /// When true, an ASTTemplateKWAndArgsInfo structure and its + /// TemplateArguments (if any) are allocated immediately after + /// the MemberExpr or, if the member expression also has a qualifier, + /// after the MemberNameQualifier structure. + bool HasTemplateKWAndArgsInfo : 1; /// \brief True if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. @@ -2059,13 +2225,13 @@ public: const DeclarationNameInfo &NameInfo, QualType ty, ExprValueKind VK, ExprObjectKind OK) : Expr(MemberExprClass, ty, VK, OK, - base->isTypeDependent(), + base->isTypeDependent(), base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), - MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), + MemberLoc(NameInfo.getLoc()), IsArrow(isarrow), + HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { assert(memberdecl->getDeclName() == NameInfo.getName()); } @@ -2073,7 +2239,7 @@ public: // NOTE: this constructor should be used only when it is known that // the member name can not provide additional syntactic info // (i.e., source locations for C++ operator names or type source info - // for constructors, destructors and conversion oeprators). + // for constructors, destructors and conversion operators). MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, SourceLocation l, QualType ty, ExprValueKind VK, ExprObjectKind OK) @@ -2081,13 +2247,14 @@ public: base->isTypeDependent(), base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), + Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, @@ -2126,22 +2293,61 @@ public: return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); } - /// \brief If the member name was qualified, retrieves the + /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { if (!hasQualifier()) return NestedNameSpecifierLoc(); - + return getMemberQualifier()->QualifierLoc; } - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgs() const { - return HasExplicitTemplateArgumentList; + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) + return 0; + + if (!HasQualifierOrFoundDecl) + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); + + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( + getMemberQualifier() + 1); + } + + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo(); + } + + /// \brief Retrieve the location of the template keyword preceding + /// the member name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the member name, if any. + SourceLocation getLAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the member name, if any. + SourceLocation getRAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; } + /// Determines whether the member name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// \brief Determines whether the member name was followed by an + /// explicit template argument list. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -2153,12 +2359,8 @@ public: /// follow the member template name. This must only be called on an /// expression with explicit template arguments. ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(HasExplicitTemplateArgumentList); - if (!HasQualifierOrFoundDecl) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); - - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( - getMemberQualifier() + 1); + assert(hasExplicitTemplateArgs()); + return *getTemplateKWAndArgsInfo(); } /// \brief Retrieve the explicit template argument list that @@ -2175,20 +2377,11 @@ public: if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } - - /// \brief Retrieve the location of the left angle bracket following the - /// member name ('<'), if any. - SourceLocation getLAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - - return getExplicitTemplateArgs().LAngleLoc; - } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) + if (!hasExplicitTemplateArgs()) return 0; return getExplicitTemplateArgs().getTemplateArgs(); @@ -2197,21 +2390,12 @@ public: /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) + if (!hasExplicitTemplateArgs()) return 0; return getExplicitTemplateArgs().NumTemplateArgs; } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - - return getExplicitTemplateArgs().RAngleLoc; - } - /// \brief Retrieve the member declaration name info. DeclarationNameInfo getMemberNameInfo() const { return DeclarationNameInfo(MemberDecl->getDeclName(), @@ -2226,9 +2410,11 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const; - - SourceLocation getExprLoc() const { return MemberLoc; } + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; + + SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } /// \brief Determine whether the base of this explicit is implicit. bool isImplicitAccess() const { @@ -2269,19 +2455,19 @@ class CompoundLiteralExpr : public Expr { /// The type as written. This can be an incomplete array type, in /// which case the actual expression type will be different. - TypeSourceInfo *TInfo; + /// The int part of the pair stores whether this expr is file scope. + llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope; Stmt *Init; - bool FileScope; public: CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, QualType T, ExprValueKind VK, Expr *init, bool fileScope) : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, - tinfo->getType()->isDependentType(), + tinfo->getType()->isDependentType(), init->isValueDependent(), (init->isInstantiationDependent() || tinfo->getType()->isInstantiationDependentType()), init->containsUnexpandedParameterPack()), - LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {} + LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} /// \brief Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) @@ -2291,16 +2477,20 @@ public: Expr *getInitializer() { return cast<Expr>(Init); } void setInitializer(Expr *E) { Init = E; } - bool isFileScope() const { return FileScope; } - void setFileScope(bool FS) { FileScope = FS; } + bool isFileScope() const { return TInfoAndScope.getInt(); } + void setFileScope(bool FS) { TInfoAndScope.setInt(FS); } SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } - TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } - void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; } + TypeSourceInfo *getTypeSourceInfo() const { + return TInfoAndScope.getPointer(); + } + void setTypeSourceInfo(TypeSourceInfo *tinfo) { + TInfoAndScope.setPointer(tinfo); + } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { // FIXME: Init should never be null. if (!Init) return SourceRange(); @@ -2352,7 +2542,7 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent()), - (ty->isInstantiationDependentType() || + (ty->isInstantiationDependentType() || (op && op->isInstantiationDependent())), (ty->containsUnexpandedParameterPack() || op->containsUnexpandedParameterPack())), @@ -2454,9 +2644,15 @@ public: static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return getSubExpr()->getSourceRange(); } + SourceLocation getLocStart() const LLVM_READONLY { + return getSubExpr()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSubExpr()->getLocEnd(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; @@ -2551,7 +2747,7 @@ public: SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); } static bool classof(const Stmt *T) { @@ -2611,6 +2807,7 @@ public: explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } + SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; } SourceLocation getOperatorLoc() const { return OpLoc; } void setOperatorLoc(SourceLocation L) { OpLoc = L; } @@ -2622,7 +2819,7 @@ public: Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); } @@ -2674,6 +2871,13 @@ public: bool isCompoundAssignmentOp() const { return isCompoundAssignmentOp(getOpcode()); } + static Opcode getOpForCompoundAssignment(Opcode Opc) { + assert(isCompoundAssignmentOp(Opc)); + if (Opc >= BO_AndAssign) + return Opcode(unsigned(Opc) - BO_AndAssign + BO_And); + else + return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul); + } static bool isShiftAssignOp(Opcode Opc) { return Opc == BO_ShlAssign || Opc == BO_ShrAssign; @@ -2842,11 +3046,11 @@ public: // the expression if the condition evaluates to false. This is // the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - + Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); } static bool classof(const Stmt *T) { @@ -2895,8 +3099,7 @@ public: SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - - OpaqueValue->setSourceExpr(common); + assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); } /// \brief Build an empty conditional operator. @@ -2928,8 +3131,8 @@ public: Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd()); } static bool classof(const Stmt *T) { @@ -2981,7 +3184,7 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AmpAmpLoc, LabelLoc); } @@ -3023,7 +3226,7 @@ public: const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } void setSubStmt(CompoundStmt *S) { SubStmt = S; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LParenLoc, RParenLoc); } @@ -3073,7 +3276,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3088,7 +3291,7 @@ public: /// \brief Retrieve the array of expressions. Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } - + /// getExpr - Return the Expr at the specified index. Expr *getExpr(unsigned Index) { assert((Index < NumExprs) && "Arg access out of range!"); @@ -3168,7 +3371,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3205,7 +3408,7 @@ public: SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TokenLoc); } static bool classof(const Stmt *T) { @@ -3251,7 +3454,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3319,10 +3522,6 @@ class InitListExpr : public Expr { /// field within the union will be initialized. llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; - /// Whether this initializer list originally had a GNU array-range - /// designator in it. This is a temporary marker used by CodeGen. - bool HadArrayRangeDesignator; - public: InitListExpr(ASTContext &C, SourceLocation lbraceloc, Expr **initexprs, unsigned numinits, @@ -3336,7 +3535,7 @@ public: /// \brief Retrieve the set of initializers. Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } - + const Expr *getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); @@ -3383,6 +3582,10 @@ public: } void setArrayFiller(Expr *filler); + /// \brief Return true if this is an array initializer and its array "filler" + /// has been set. + bool hasArrayFiller() const { return getArrayFiller(); } + /// \brief If this initializes a union, specifies which field in the /// union to initialize. /// @@ -3417,12 +3620,21 @@ public: InitListExpr *getSyntacticForm() const { return SyntacticForm; } void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; } - bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; } + bool hadArrayRangeDesignator() const { + return InitListExprBits.HadArrayRangeDesignator != 0; + } void sawArrayRangeDesignator(bool ARD = true) { - HadArrayRangeDesignator = ARD; + InitListExprBits.HadArrayRangeDesignator = ARD; + } + + bool initializesStdInitializerList() const { + return InitListExprBits.InitializesStdInitializerList != 0; + } + void setInitializesStdInitializerList(bool ISIL = true) { + InitListExprBits.InitializesStdInitializerList = ISIL; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == InitListExprClass; @@ -3490,15 +3702,15 @@ private: /// The number of designators in this initializer expression. unsigned NumDesignators : 15; - /// \brief The designators in this designated initialization - /// expression. - Designator *Designators; - /// The number of subexpressions of this initializer expression, /// which contains both the initializer and any additional /// expressions used by array and array-range designators. unsigned NumSubExprs : 16; + /// \brief The designators in this designated initialization + /// expression. + Designator *Designators; + DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators, const Designator *Designators, @@ -3508,7 +3720,7 @@ private: explicit DesignatedInitExpr(unsigned NumSubExprs) : Expr(DesignatedInitExprClass, EmptyShell()), - NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } + NumDesignators(0), NumSubExprs(NumSubExprs), Designators(0) { } public: /// A field designator, e.g., ".x". @@ -3658,7 +3870,7 @@ public: SourceLocation getEndLocation() const { return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getStartLocation(), getEndLocation()); } }; @@ -3707,7 +3919,7 @@ public: Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } - void setDesignators(ASTContext &C, const Designator *Desigs, + void setDesignators(ASTContext &C, const Designator *Desigs, unsigned NumDesigs); Expr *getArrayIndex(const Designator& D); @@ -3760,7 +3972,7 @@ public: SourceRange getDesignatorsSourceRange() const; - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; @@ -3797,7 +4009,7 @@ public: } static bool classof(const ImplicitValueInitExpr *) { return true; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } @@ -3813,7 +4025,7 @@ class ParenListExpr : public Expr { public: ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, - unsigned numexprs, SourceLocation rparenloc, QualType T); + unsigned numexprs, SourceLocation rparenloc); /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -3835,7 +4047,7 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LParenLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3853,9 +4065,9 @@ public: }; -/// \brief Represents a C1X generic selection. +/// \brief Represents a C11 generic selection. /// -/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling +/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling /// expression, followed by one or more generic associations. Each generic /// association specifies a type name and an expression, or "default" and an /// expression (in which case it is known as a default generic association). @@ -3950,7 +4162,7 @@ public: const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(GenericLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -4016,7 +4228,7 @@ public: /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const; - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBase()->getLocStart(), AccessorLoc); } @@ -4042,9 +4254,8 @@ protected: public: BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), false, - // FIXME: Check for instantiate-dependence in the statement? - ty->isInstantiationDependentType(), + ty->isDependentType(), ty->isDependentType(), + ty->isInstantiationDependentType() || BD->isDependentContext(), false), TheBlock(BD) {} @@ -4060,12 +4271,12 @@ public: const Stmt *getBody() const; Stmt *getBody(); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCaretLocation(), getBody()->getLocEnd()); } /// getFunctionType - Return the underlying function type for this block. - const FunctionType *getFunctionType() const; + const FunctionProtoType *getFunctionType() const; static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; @@ -4076,46 +4287,6 @@ public: child_range children() { return child_range(); } }; -/// BlockDeclRefExpr - A reference to a local variable declared in an -/// enclosing scope. -class BlockDeclRefExpr : public Expr { - VarDecl *D; - SourceLocation Loc; - bool IsByRef : 1; - bool ConstQualAdded : 1; -public: - BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, - SourceLocation l, bool ByRef, bool constAdded = false); - - // \brief Build an empty reference to a declared variable in a - // block. - explicit BlockDeclRefExpr(EmptyShell Empty) - : Expr(BlockDeclRefExprClass, Empty) { } - - VarDecl *getDecl() { return D; } - const VarDecl *getDecl() const { return D; } - void setDecl(VarDecl *VD) { D = VD; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - SourceRange getSourceRange() const { return SourceRange(Loc); } - - bool isByRef() const { return IsByRef; } - void setByRef(bool BR) { IsByRef = BR; } - - bool isConstQualAdded() const { return ConstQualAdded; } - void setConstQualAdded(bool C) { ConstQualAdded = C; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BlockDeclRefExprClass; - } - static bool classof(const BlockDeclRefExpr *) { return true; } - - // Iterators - child_range children() { return child_range(); } -}; - /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] /// This AST node provides support for reinterpreting a type to another /// type of the same size. @@ -4127,12 +4298,12 @@ private: friend class ASTReader; friend class ASTStmtReader; explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} - + public: AsTypeExpr(Expr* SrcExpr, QualType DstType, ExprValueKind VK, ExprObjectKind OK, SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(AsTypeExprClass, DstType, VK, OK, + : Expr(AsTypeExprClass, DstType, VK, OK, DstType->isDependentType(), DstType->isDependentType() || SrcExpr->isValueDependent(), (DstType->isInstantiationDependentType() || @@ -4140,7 +4311,7 @@ public: (DstType->containsUnexpandedParameterPack() || SrcExpr->containsUnexpandedParameterPack())), SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} - + /// getSrcExpr - Return the Expr to be converted. Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } @@ -4149,83 +4320,218 @@ public: /// getRParenLoc - Return the location of final right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } - + static bool classof(const Stmt *T) { - return T->getStmtClass() == AsTypeExprClass; + return T->getStmtClass() == AsTypeExprClass; } static bool classof(const AsTypeExpr *) { return true; } - + // Iterators child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } }; +/// PseudoObjectExpr - An expression which accesses a pseudo-object +/// l-value. A pseudo-object is an abstract object, accesses to which +/// are translated to calls. The pseudo-object expression has a +/// syntactic form, which shows how the expression was actually +/// written in the source code, and a semantic form, which is a series +/// of expressions to be executed in order which detail how the +/// operation is actually evaluated. Optionally, one of the semantic +/// forms may also provide a result value for the expression. +/// +/// If any of the semantic-form expressions is an OpaqueValueExpr, +/// that OVE is required to have a source expression, and it is bound +/// to the result of that source expression. Such OVEs may appear +/// only in subsequent semantic-form expressions and as +/// sub-expressions of the syntactic form. +/// +/// PseudoObjectExpr should be used only when an operation can be +/// usefully described in terms of fairly simple rewrite rules on +/// objects and functions that are meant to be used by end-developers. +/// For example, under the Itanium ABI, dynamic casts are implemented +/// as a call to a runtime function called __dynamic_cast; using this +/// class to describe that would be inappropriate because that call is +/// not really part of the user-visible semantics, and instead the +/// cast is properly reflected in the AST and IR-generation has been +/// taught to generate the call as necessary. In contrast, an +/// Objective-C property access is semantically defined to be +/// equivalent to a particular message send, and this is very much +/// part of the user model. The name of this class encourages this +/// modelling design. +class PseudoObjectExpr : public Expr { + // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions. + // Always at least two, because the first sub-expression is the + // syntactic form. + + // PseudoObjectExprBits.ResultIndex - The index of the + // sub-expression holding the result. 0 means the result is void, + // which is unambiguous because it's the index of the syntactic + // form. Note that this is therefore 1 higher than the value passed + // in to Create, which is an index within the semantic forms. + // Note also that ASTStmtWriter assumes this encoding. + + Expr **getSubExprsBuffer() { return reinterpret_cast<Expr**>(this + 1); } + const Expr * const *getSubExprsBuffer() const { + return reinterpret_cast<const Expr * const *>(this + 1); + } + + friend class ASTStmtReader; + + PseudoObjectExpr(QualType type, ExprValueKind VK, + Expr *syntactic, ArrayRef<Expr*> semantic, + unsigned resultIndex); + + PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs); + + unsigned getNumSubExprs() const { + return PseudoObjectExprBits.NumSubExprs; + } + +public: + /// NoResult - A value for the result index indicating that there is + /// no semantic result. + enum { NoResult = ~0U }; + + static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic, + ArrayRef<Expr*> semantic, + unsigned resultIndex); + + static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell, + unsigned numSemanticExprs); + + /// Return the syntactic form of this expression, i.e. the + /// expression it actually looks like. Likely to be expressed in + /// terms of OpaqueValueExprs bound in the semantic form. + Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; } + const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; } + + /// Return the index of the result-bearing expression into the semantics + /// expressions, or PseudoObjectExpr::NoResult if there is none. + unsigned getResultExprIndex() const { + if (PseudoObjectExprBits.ResultIndex == 0) return NoResult; + return PseudoObjectExprBits.ResultIndex - 1; + } + + /// Return the result-bearing expression, or null if there is none. + Expr *getResultExpr() { + if (PseudoObjectExprBits.ResultIndex == 0) + return 0; + return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex]; + } + const Expr *getResultExpr() const { + return const_cast<PseudoObjectExpr*>(this)->getResultExpr(); + } + + unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; } + + typedef Expr * const *semantics_iterator; + typedef const Expr * const *const_semantics_iterator; + semantics_iterator semantics_begin() { + return getSubExprsBuffer() + 1; + } + const_semantics_iterator semantics_begin() const { + return getSubExprsBuffer() + 1; + } + semantics_iterator semantics_end() { + return getSubExprsBuffer() + getNumSubExprs(); + } + const_semantics_iterator semantics_end() const { + return getSubExprsBuffer() + getNumSubExprs(); + } + Expr *getSemanticExpr(unsigned index) { + assert(index + 1 < getNumSubExprs()); + return getSubExprsBuffer()[index + 1]; + } + const Expr *getSemanticExpr(unsigned index) const { + return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index); + } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getSyntacticForm()->getExprLoc(); + } + SourceRange getSourceRange() const LLVM_READONLY { + return getSyntacticForm()->getSourceRange(); + } + + child_range children() { + Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer()); + return child_range(cs, cs + getNumSubExprs()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PseudoObjectExprClass; + } + static bool classof(const PseudoObjectExpr *) { return true; } +}; + /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the -/// similarly-named C++0x instructions. All of these instructions take one -/// primary pointer and at least one memory order. +/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>. +/// All of these instructions take one primary pointer and at least one memory +/// order. class AtomicExpr : public Expr { public: - enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg, - Add, Sub, And, Or, Xor }; + enum AtomicOp { +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, +#include "clang/Basic/Builtins.def" + // Avoid trailing comma + BI_First = 0 + }; + private: - enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR }; + enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; unsigned NumSubExprs; SourceLocation BuiltinLoc, RParenLoc; AtomicOp Op; + friend class ASTStmtReader; + public: AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t, AtomicOp op, SourceLocation RP); + /// \brief Determine the number of arguments the specified atomic builtin + /// should have. + static unsigned getNumSubExprs(AtomicOp Op); + /// \brief Build an empty AtomicExpr. explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } Expr *getPtr() const { return cast<Expr>(SubExprs[PTR]); } - void setPtr(Expr *E) { - SubExprs[PTR] = E; - } Expr *getOrder() const { return cast<Expr>(SubExprs[ORDER]); } - void setOrder(Expr *E) { - SubExprs[ORDER] = E; - } Expr *getVal1() const { - assert(NumSubExprs >= 3); + if (Op == AO__c11_atomic_init) + return cast<Expr>(SubExprs[ORDER]); + assert(NumSubExprs > VAL1); return cast<Expr>(SubExprs[VAL1]); } - void setVal1(Expr *E) { - assert(NumSubExprs >= 3); - SubExprs[VAL1] = E; - } Expr *getOrderFail() const { - assert(NumSubExprs == 5); + assert(NumSubExprs > ORDER_FAIL); return cast<Expr>(SubExprs[ORDER_FAIL]); } - void setOrderFail(Expr *E) { - assert(NumSubExprs == 5); - SubExprs[ORDER_FAIL] = E; - } Expr *getVal2() const { - assert(NumSubExprs == 5); + if (Op == AO__atomic_exchange) + return cast<Expr>(SubExprs[ORDER_FAIL]); + assert(NumSubExprs > VAL2); return cast<Expr>(SubExprs[VAL2]); } - void setVal2(Expr *E) { - assert(NumSubExprs == 5); - SubExprs[VAL2] = E; + Expr *getWeak() const { + assert(NumSubExprs > WEAK); + return cast<Expr>(SubExprs[WEAK]); } AtomicOp getOp() const { return Op; } - void setOp(AtomicOp op) { Op = op; } unsigned getNumSubExprs() { return NumSubExprs; } - void setNumSubExprs(unsigned num) { NumSubExprs = num; } Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } @@ -4234,17 +4540,16 @@ public: } bool isCmpXChg() const { - return getOp() == AtomicExpr::CmpXchgStrong || - getOp() == AtomicExpr::CmpXchgWeak; + return getOp() == AO__c11_atomic_compare_exchange_strong || + getOp() == AO__c11_atomic_compare_exchange_weak || + getOp() == AO__atomic_compare_exchange || + getOp() == AO__atomic_compare_exchange_n; } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h index 3cc09cd..b69693d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h @@ -14,11 +14,13 @@ #ifndef LLVM_CLANG_AST_EXPRCXX_H #define LLVM_CLANG_AST_EXPRCXX_H -#include "clang/Basic/TypeTraits.h" -#include "clang/Basic/ExpressionTraits.h" #include "clang/AST/Expr.h" #include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" +#include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/TypeTraits.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -72,7 +74,7 @@ public: /// bracket. SourceLocation getOperatorLoc() const { return getRParenLoc(); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; @@ -101,7 +103,7 @@ public: /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". Expr *getImplicitObjectArgument() const; - + /// Retrieves the declaration of the called method. CXXMethodDecl *getMethodDecl() const; @@ -158,7 +160,7 @@ class CXXNamedCastExpr : public ExplicitCastExpr { private: SourceLocation Loc; // the location of the casting op SourceLocation RParenLoc; // the location of the right parenthesis - + protected: CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned PathSize, @@ -171,7 +173,7 @@ protected: : ExplicitCastExpr(SC, Shell, PathSize) { } friend class ASTStmtReader; - + public: const char *getCastName() const; @@ -181,8 +183,8 @@ public: /// \brief Retrieve the location of the closing parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParenLoc); } static bool classof(const Stmt *T) { @@ -199,7 +201,8 @@ public: static bool classof(const CXXNamedCastExpr *) { return true; } }; -/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]). +/// CXXStaticCastExpr - A C++ @c static_cast expression +/// (C++ [expr.static.cast]). /// /// This expression node represents a C++ static cast, e.g., /// @c static_cast<int>(1.0). @@ -217,7 +220,7 @@ public: static CXXStaticCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L, + TypeSourceInfo *Written, SourceLocation L, SourceLocation RParenLoc); static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); @@ -248,9 +251,9 @@ public: static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L, + TypeSourceInfo *Written, SourceLocation L, SourceLocation RParenLoc); - + static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -271,7 +274,7 @@ public: class CXXReinterpretCastExpr : public CXXNamedCastExpr { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, - TypeSourceInfo *writtenTy, SourceLocation l, + TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc) : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, pathSize, writtenTy, l, RParenLoc) {} @@ -283,7 +286,7 @@ public: static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, - TypeSourceInfo *WrittenTy, SourceLocation L, + TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc); static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); @@ -301,9 +304,9 @@ public: /// @c const_cast<char*>(PtrToConstChar). class CXXConstCastExpr : public CXXNamedCastExpr { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l, + TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, + : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, 0, writtenTy, l, RParenLoc) {} explicit CXXConstCastExpr(EmptyShell Empty) @@ -312,7 +315,7 @@ class CXXConstCastExpr : public CXXNamedCastExpr { public: static CXXConstCastExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, Expr *Op, - TypeSourceInfo *WrittenTy, SourceLocation L, + TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc); static CXXConstCastExpr *CreateEmpty(ASTContext &Context); @@ -322,6 +325,67 @@ public: static bool classof(const CXXConstCastExpr *) { return true; } }; +/// UserDefinedLiteral - A call to a literal operator (C++11 [over.literal]) +/// written as a user-defined literal (C++11 [lit.ext]). +/// +/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this +/// is semantically equivalent to a normal call, this AST node provides better +/// information about the syntactic representation of the literal. +/// +/// Since literal operators are never found by ADL and can only be declared at +/// namespace scope, a user-defined literal is never dependent. +class UserDefinedLiteral : public CallExpr { + /// \brief The location of a ud-suffix within the literal. + SourceLocation UDSuffixLoc; + +public: + UserDefinedLiteral(ASTContext &C, Expr *Fn, Expr **Args, unsigned NumArgs, + QualType T, ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc) + : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, NumArgs, T, VK, + LitEndLoc), UDSuffixLoc(SuffixLoc) {} + explicit UserDefinedLiteral(ASTContext &C, EmptyShell Empty) + : CallExpr(C, UserDefinedLiteralClass, Empty) {} + + /// The kind of literal operator which is invoked. + enum LiteralOperatorKind { + LOK_Raw, ///< Raw form: operator "" X (const char *) + LOK_Template, ///< Raw form: operator "" X<cs...> () + LOK_Integer, ///< operator "" X (unsigned long long) + LOK_Floating, ///< operator "" X (long double) + LOK_String, ///< operator "" X (const CharT *, size_t) + LOK_Character ///< operator "" X (CharT) + }; + + /// getLiteralOperatorKind - Returns the kind of literal operator invocation + /// which this expression represents. + LiteralOperatorKind getLiteralOperatorKind() const; + + /// getCookedLiteral - If this is not a raw user-defined literal, get the + /// underlying cooked literal (representing the literal with the suffix + /// removed). + Expr *getCookedLiteral(); + const Expr *getCookedLiteral() const { + return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); + } + + /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression. + /// For a string literal, there may be multiple identical suffixes. This + /// returns the first. + SourceLocation getUDSuffixLoc() const { return getRParenLoc(); } + + /// getUDSuffix - Returns the ud-suffix specified for this literal. + const IdentifierInfo *getUDSuffix() const; + + static bool classof(const Stmt *S) { + return S->getStmtClass() == UserDefinedLiteralClass; + } + static bool classof(const UserDefinedLiteral *) { return true; } + + friend class ASTStmtReader; + friend class ASTStmtWriter; +}; + /// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal. /// class CXXBoolLiteralExpr : public Expr { @@ -339,7 +403,7 @@ public: bool getValue() const { return Value; } void setValue(bool V) { Value = V; } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -365,7 +429,7 @@ public: explicit CXXNullPtrLiteralExpr(EmptyShell Empty) : Expr(CXXNullPtrLiteralExprClass, Empty) { } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -398,7 +462,7 @@ public: Operand->getType()->isInstantiationDependentType(), Operand->getType()->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } - + CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, // typeid is never type-dependent (C++ [temp.dep.expr]p4) @@ -416,9 +480,9 @@ public: else Operand = (TypeSourceInfo*)0; } - + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } - + /// \brief Retrieves the type operand of this typeid() expression after /// various required adjustments (removing reference types, cv-qualifiers). QualType getTypeOperand() const; @@ -433,20 +497,20 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); Operand = TSI; } - + Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - + void setExprOperand(Expr *E) { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); Operand = E; } - - SourceRange getSourceRange() const { return Range; } + + SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTypeidExprClass; } @@ -476,7 +540,7 @@ public: Operand->getType()->isInstantiationDependentType(), Operand->getType()->containsUnexpandedParameterPack()), Operand(Operand), Range(R) { } - + CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R) : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, Operand->isTypeDependent(), @@ -491,9 +555,9 @@ public: else Operand = (TypeSourceInfo*)0; } - + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } - + /// \brief Retrieves the type operand of this __uuidof() expression after /// various required adjustments (removing reference types, cv-qualifiers). QualType getTypeOperand() const; @@ -508,20 +572,20 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); Operand = TSI; } - + Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - + void setExprOperand(Expr *E) { assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); Operand = E; } - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUuidofExprClass; } @@ -549,7 +613,7 @@ public: class CXXThisExpr : public Expr { SourceLocation Loc; bool Implicit : 1; - + public: CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary, @@ -565,11 +629,11 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } bool isImplicit() const { return Implicit; } void setImplicit(bool I) { Implicit = I; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXThisExprClass; } @@ -588,9 +652,9 @@ class CXXThrowExpr : public Expr { SourceLocation ThrowLoc; /// \brief Whether the thrown variable (if any) is in scope. unsigned IsThrownVariableInScope : 1; - + friend class ASTStmtReader; - + public: // Ty is the void type which is used as the result type of the // exepression. The l is the location of the throw keyword. expr @@ -614,8 +678,8 @@ public: /// This information is required to determine whether the NRVO can apply to /// this variable. bool isThrownVariableInScope() const { return IsThrownVariableInScope; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { if (getSubExpr() == 0) return SourceRange(ThrowLoc, ThrowLoc); return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd()); @@ -639,16 +703,16 @@ public: class CXXDefaultArgExpr : public Expr { /// \brief The parameter whose default is being used. /// - /// When the bit is set, the subexpression is stored after the + /// When the bit is set, the subexpression is stored after the /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's /// actual default expression is the subexpression. llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param; /// \brief The location where the default argument expression was used. SourceLocation Loc; - + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) - : Expr(SC, + : Expr(SC, param->hasUnparsedDefaultArg() ? param->getType().getNonReferenceType() : param->getDefaultArg()->getType(), @@ -656,19 +720,19 @@ class CXXDefaultArgExpr : public Expr { param->getDefaultArg()->getObjectKind(), false, false, false, false), Param(param, false), Loc(Loc) { } - CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, Expr *SubExpr) : Expr(SC, SubExpr->getType(), SubExpr->getValueKind(), SubExpr->getObjectKind(), - false, false, false, false), + false, false, false, false), Param(param, true), Loc(Loc) { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } - + public: CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} - + // Param is the parameter whose default argument is used by this // expression. static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, @@ -678,32 +742,32 @@ public: // Param is the parameter whose default argument is used by this // expression, and SubExpr is the expression that will actually be used. - static CXXDefaultArgExpr *Create(ASTContext &C, + static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, + ParmVarDecl *Param, Expr *SubExpr); - + // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param.getPointer(); } ParmVarDecl *getParam() { return Param.getPointer(); } - + // Retrieve the actual argument to the function call. - const Expr *getExpr() const { + const Expr *getExpr() const { if (Param.getInt()) return *reinterpret_cast<Expr const * const*> (this + 1); - return getParam()->getDefaultArg(); + return getParam()->getDefaultArg(); } - Expr *getExpr() { + Expr *getExpr() { if (Param.getInt()) return *reinterpret_cast<Expr **> (this + 1); - return getParam()->getDefaultArg(); + return getParam()->getDefaultArg(); } - /// \brief Retrieve the location where this default argument was actually + /// \brief Retrieve the location where this default argument was actually /// used. SourceLocation getUsedLocation() const { return Loc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { // Default argument expressions have no representation in the // source, so they have an empty source range. return SourceRange(); @@ -734,6 +798,9 @@ public: const CXXDestructorDecl *Destructor); const CXXDestructorDecl *getDestructor() const { return Destructor; } + void setDestructor(const CXXDestructorDecl *Dtor) { + Destructor = Dtor; + } }; /// \brief Represents binding an expression to a temporary. @@ -757,7 +824,7 @@ class CXXBindTemporaryExpr : public Expr { CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), - VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), + VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), SubExpr->isValueDependent(), SubExpr->isInstantiationDependent(), SubExpr->containsUnexpandedParameterPack()), @@ -766,7 +833,7 @@ class CXXBindTemporaryExpr : public Expr { public: CXXBindTemporaryExpr(EmptyShell Empty) : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} - + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); @@ -778,7 +845,7 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SubExpr->getSourceRange(); } @@ -801,7 +868,7 @@ public: CK_VirtualBase, CK_Delegating }; - + private: CXXConstructorDecl *Constructor; @@ -810,6 +877,7 @@ private: unsigned NumArgs : 16; bool Elidable : 1; bool HadMultipleCandidates : 1; + bool ListInitialization : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -820,39 +888,43 @@ protected: CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, bool HadMultipleCandidates, - bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete, - SourceRange ParenRange = SourceRange()); + bool ListInitialization, + bool ZeroInitialization, + ConstructionKind ConstructKind, + SourceRange ParenRange); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(0), - HadMultipleCandidates(false), ZeroInitialization(0), - ConstructKind(0), Args(0) { } + : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(false), + HadMultipleCandidates(false), ListInitialization(false), + ZeroInitialization(false), ConstructKind(0), Args(0) + { } public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) : Expr(CXXConstructExprClass, Empty), Constructor(0), - NumArgs(0), Elidable(0), HadMultipleCandidates(false), - ZeroInitialization(0), ConstructKind(0), Args(0) { } + NumArgs(0), Elidable(false), HadMultipleCandidates(false), + ListInitialization(false), ZeroInitialization(false), + ConstructKind(0), Args(0) + { } static CXXConstructExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool HadMultipleCandidates, - bool ZeroInitialization = false, - ConstructionKind ConstructKind = CK_Complete, - SourceRange ParenRange = SourceRange()); - + bool ListInitialization, + bool ZeroInitialization, + ConstructionKind ConstructKind, + SourceRange ParenRange); CXXConstructorDecl* getConstructor() const { return Constructor; } void setConstructor(CXXConstructorDecl *C) { Constructor = C; } - + SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation Loc) { this->Loc = Loc; } - + /// \brief Whether this construction is elidable. bool isElidable() const { return Elidable; } void setElidable(bool E) { Elidable = E; } @@ -862,22 +934,26 @@ public: bool hadMultipleCandidates() const { return HadMultipleCandidates; } void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } + /// \brief Whether this constructor call was written as list-initialization. + bool isListInitialization() const { return ListInitialization; } + void setListInitialization(bool V) { ListInitialization = V; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } void setRequiresZeroInitialization(bool ZeroInit) { ZeroInitialization = ZeroInit; } - + /// \brief Determines whether this constructor is actually constructing /// a base class (rather than a complete object). ConstructionKind getConstructionKind() const { return (ConstructionKind)ConstructKind; } - void setConstructionKind(ConstructionKind CK) { + void setConstructionKind(ConstructionKind CK) { ConstructKind = CK; } - + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -905,7 +981,7 @@ public: Args[Arg] = ArgExpr; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; SourceRange getParenRange() const { return ParenRange; } static bool classof(const Stmt *T) { @@ -933,7 +1009,7 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, Expr *castExpr, unsigned pathSize, - SourceLocation rParenLoc) + SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, pathSize, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} @@ -957,7 +1033,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TyBeginLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -971,7 +1047,7 @@ public: /// /// This expression type represents a C++ "functional" cast /// (C++[expr.type.conv]) with N != 1 arguments that invokes a -/// constructor to build a temporary object. With N == 1 arguments the +/// constructor to build a temporary object. With N == 1 arguments the /// functional cast expression will be represented by CXXFunctionalCastExpr. /// Example: /// @code @@ -996,8 +1072,8 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return Type; } - SourceRange getSourceRange() const; - + SourceRange getSourceRange() const LLVM_READONLY; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } @@ -1006,6 +1082,303 @@ public: friend class ASTStmtReader; }; +/// \brief A C++ lambda expression, which produces a function object +/// (of unspecified type) that can be invoked later. +/// +/// Example: +/// \code +/// void low_pass_filter(std::vector<double> &values, double cutoff) { +/// values.erase(std::remove_if(values.begin(), values.end(), +// [=](double value) { return value > cutoff; }); +/// } +/// \endcode +/// +/// Lambda expressions can capture local variables, either by copying +/// the values of those local variables at the time the function +/// object is constructed (not when it is called!) or by holding a +/// reference to the local variable. These captures can occur either +/// implicitly or can be written explicitly between the square +/// brackets ([...]) that start the lambda expression. +class LambdaExpr : public Expr { + enum { + /// \brief Flag used by the Capture class to indicate that the given + /// capture was implicit. + Capture_Implicit = 0x01, + + /// \brief Flag used by the Capture class to indciate that the + /// given capture was by-copy. + Capture_ByCopy = 0x02 + }; + + /// \brief The source range that covers the lambda introducer ([...]). + SourceRange IntroducerRange; + + /// \brief The number of captures. + unsigned NumCaptures : 16; + + /// \brief The default capture kind, which is a value of type + /// LambdaCaptureDefault. + unsigned CaptureDefault : 2; + + /// \brief Whether this lambda had an explicit parameter list vs. an + /// implicit (and empty) parameter list. + unsigned ExplicitParams : 1; + + /// \brief Whether this lambda had the result type explicitly specified. + unsigned ExplicitResultType : 1; + + /// \brief Whether there are any array index variables stored at the end of + /// this lambda expression. + unsigned HasArrayIndexVars : 1; + + /// \brief The location of the closing brace ('}') that completes + /// the lambda. + /// + /// The location of the brace is also available by looking up the + /// function call operator in the lambda class. However, it is + /// stored here to improve the performance of getSourceRange(), and + /// to avoid having to deserialize the function call operator from a + /// module file just to determine the source range. + SourceLocation ClosingBrace; + + // Note: The capture initializers are stored directly after the lambda + // expression, along with the index variables used to initialize by-copy + // array captures. + +public: + /// \brief Describes the capture of either a variable or 'this'. + class Capture { + llvm::PointerIntPair<VarDecl *, 2> VarAndBits; + SourceLocation Loc; + SourceLocation EllipsisLoc; + + friend class ASTStmtReader; + friend class ASTStmtWriter; + + public: + /// \brief Create a new capture. + /// + /// \param Loc The source location associated with this capture. + /// + /// \param Kind The kind of capture (this, byref, bycopy). + /// + /// \param Implicit Whether the capture was implicit or explicit. + /// + /// \param Var The local variable being captured, or null if capturing this. + /// + /// \param EllipsisLoc The location of the ellipsis (...) for a + /// capture that is a pack expansion, or an invalid source + /// location to indicate that this is not a pack expansion. + Capture(SourceLocation Loc, bool Implicit, + LambdaCaptureKind Kind, VarDecl *Var = 0, + SourceLocation EllipsisLoc = SourceLocation()); + + /// \brief Determine the kind of capture. + LambdaCaptureKind getCaptureKind() const; + + /// \brief Determine whether this capture handles the C++ 'this' + /// pointer. + bool capturesThis() const { return VarAndBits.getPointer() == 0; } + + /// \brief Determine whether this capture handles a variable. + bool capturesVariable() const { return VarAndBits.getPointer() != 0; } + + /// \brief Retrieve the declaration of the local variable being + /// captured. + /// + /// This operation is only valid if this capture does not capture + /// 'this'. + VarDecl *getCapturedVar() const { + assert(!capturesThis() && "No variable available for 'this' capture"); + return VarAndBits.getPointer(); + } + + /// \brief Determine whether this was an implicit capture (not + /// written between the square brackets introducing the lambda). + bool isImplicit() const { return VarAndBits.getInt() & Capture_Implicit; } + + /// \brief Determine whether this was an explicit capture, written + /// between the square brackets introducing the lambda. + bool isExplicit() const { return !isImplicit(); } + + /// \brief Retrieve the source location of the capture. + /// + /// For an explicit capture, this returns the location of the + /// explicit capture in the source. For an implicit capture, this + /// returns the location at which the variable or 'this' was first + /// used. + SourceLocation getLocation() const { return Loc; } + + /// \brief Determine whether this capture is a pack expansion, + /// which captures a function parameter pack. + bool isPackExpansion() const { return EllipsisLoc.isValid(); } + + /// \brief Retrieve the location of the ellipsis for a capture + /// that is a pack expansion. + SourceLocation getEllipsisLoc() const { + assert(isPackExpansion() && "No ellipsis location for a non-expansion"); + return EllipsisLoc; + } + }; + +private: + /// \brief Construct a lambda expression. + LambdaExpr(QualType T, SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + ArrayRef<Capture> Captures, + bool ExplicitParams, + bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, + ArrayRef<VarDecl *> ArrayIndexVars, + ArrayRef<unsigned> ArrayIndexStarts, + SourceLocation ClosingBrace); + + /// \brief Construct an empty lambda expression. + LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) + : Expr(LambdaExprClass, Empty), + NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), + ExplicitResultType(false), HasArrayIndexVars(true) { + getStoredStmts()[NumCaptures] = 0; + } + + Stmt **getStoredStmts() const { + return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1); + } + + /// \brief Retrieve the mapping from captures to the first array index + /// variable. + unsigned *getArrayIndexStarts() const { + return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1); + } + + /// \brief Retrieve the complete set of array-index variables. + VarDecl **getArrayIndexVars() const { + return reinterpret_cast<VarDecl **>( + getArrayIndexStarts() + NumCaptures + 1); + } + +public: + /// \brief Construct a new lambda expression. + static LambdaExpr *Create(ASTContext &C, + CXXRecordDecl *Class, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + ArrayRef<Capture> Captures, + bool ExplicitParams, + bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, + ArrayRef<VarDecl *> ArrayIndexVars, + ArrayRef<unsigned> ArrayIndexStarts, + SourceLocation ClosingBrace); + + /// \brief Construct a new lambda expression that will be deserialized from + /// an external source. + static LambdaExpr *CreateDeserialized(ASTContext &C, unsigned NumCaptures, + unsigned NumArrayIndexVars); + + /// \brief Determine the default capture kind for this lambda. + LambdaCaptureDefault getCaptureDefault() const { + return static_cast<LambdaCaptureDefault>(CaptureDefault); + } + + /// \brief An iterator that walks over the captures of the lambda, + /// both implicit and explicit. + typedef const Capture *capture_iterator; + + /// \brief Retrieve an iterator pointing to the first lambda capture. + capture_iterator capture_begin() const; + + /// \brief Retrieve an iterator pointing past the end of the + /// sequence of lambda captures. + capture_iterator capture_end() const; + + /// \brief Determine the number of captures in this lambda. + unsigned capture_size() const { return NumCaptures; } + + /// \brief Retrieve an iterator pointing to the first explicit + /// lambda capture. + capture_iterator explicit_capture_begin() const; + + /// \brief Retrieve an iterator pointing past the end of the sequence of + /// explicit lambda captures. + capture_iterator explicit_capture_end() const; + + /// \brief Retrieve an iterator pointing to the first implicit + /// lambda capture. + capture_iterator implicit_capture_begin() const; + + /// \brief Retrieve an iterator pointing past the end of the sequence of + /// implicit lambda captures. + capture_iterator implicit_capture_end() const; + + /// \brief Iterator that walks over the capture initialization + /// arguments. + typedef Expr **capture_init_iterator; + + /// \brief Retrieve the first initialization argument for this + /// lambda expression (which initializes the first capture field). + capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr **>(getStoredStmts()); + } + + /// \brief Retrieve the iterator pointing one past the last + /// initialization argument for this lambda expression. + capture_init_iterator capture_init_end() const { + return capture_init_begin() + NumCaptures; + } + + /// \brief Retrieve the set of index variables used in the capture + /// initializer of an array captured by copy. + /// + /// \param Iter The iterator that points at the capture initializer for + /// which we are extracting the corresponding index variables. + ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const; + + /// \brief Retrieve the source range covering the lambda introducer, + /// which contains the explicit capture list surrounded by square + /// brackets ([...]). + SourceRange getIntroducerRange() const { return IntroducerRange; } + + /// \brief Retrieve the class that corresponds to the lambda, which + /// stores the captures in its fields and provides the various + /// operations permitted on a lambda (copying, calling). + CXXRecordDecl *getLambdaClass() const; + + /// \brief Retrieve the function call operator associated with this + /// lambda expression. + CXXMethodDecl *getCallOperator() const; + + /// \brief Retrieve the body of the lambda. + CompoundStmt *getBody() const; + + /// \brief Determine whether the lambda is mutable, meaning that any + /// captures values can be modified. + bool isMutable() const; + + /// \brief Determine whether this lambda has an explicit parameter + /// list vs. an implicit (empty) parameter list. + bool hasExplicitParameters() const { return ExplicitParams; } + + /// \brief Whether this lambda had its result type explicitly specified. + bool hasExplicitResultType() const { return ExplicitResultType; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == LambdaExprClass; + } + static bool classof(const LambdaExpr *) { return true; } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(IntroducerRange.getBegin(), ClosingBrace); + } + + child_range children() { + return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); + } + + friend class ASTStmtReader; + friend class ASTStmtWriter; +}; + /// CXXScalarValueInitExpr - [C++ 5.2.3p2] /// Expression "T()" which creates a value-initialized rvalue of type /// T, which is a non-class type. @@ -1015,9 +1388,9 @@ class CXXScalarValueInitExpr : public Expr { TypeSourceInfo *TypeInfo; friend class ASTStmtReader; - + public: - /// \brief Create an explicitly-written scalar-value initialization + /// \brief Create an explicitly-written scalar-value initialization /// expression. CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, @@ -1032,10 +1405,10 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return TypeInfo; } - + SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; @@ -1049,68 +1422,63 @@ public: /// CXXNewExpr - A new expression for memory allocation and constructor calls, /// e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { - // Was the usage ::new, i.e. is the global new to be used? - bool GlobalNew : 1; - // Is there an initializer? If not, built-ins are uninitialized, else they're - // value-initialized. - bool Initializer : 1; - // Do we allocate an array? If so, the first SubExpr is the size expression. - bool Array : 1; - // If this is an array allocation, does the usual deallocation - // function for the allocated type want to know the allocated size? - bool UsualArrayDeleteWantsSize : 1; - // Whether the referred constructor (if any) was resolved from an - // overload set having size greater than 1. - bool HadMultipleCandidates : 1; - // The number of placement new arguments. - unsigned NumPlacementArgs : 13; - // The number of constructor arguments. This may be 1 even for non-class - // types; use the pseudo copy constructor. - unsigned NumConstructorArgs : 14; - // Contains an optional array size expression, any number of optional - // placement arguments, and any number of optional constructor arguments, - // in that order. + // Contains an optional array size expression, an optional initialization + // expression, and any number of optional placement arguments, in that order. Stmt **SubExprs; // Points to the allocation function used. FunctionDecl *OperatorNew; // Points to the deallocation function used in case of error. May be null. FunctionDecl *OperatorDelete; - // Points to the constructor used. Cannot be null if AllocType is a record; - // it would still point at the default constructor (even an implicit one). - // Must be null for all other types. - CXXConstructorDecl *Constructor; /// \brief The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; - - /// \brief If the allocated type was expressed as a parenthesized type-id, + + /// \brief If the allocated type was expressed as a parenthesized type-id, /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; - + + /// \brief Location of the first token. SourceLocation StartLoc; - SourceLocation EndLoc; - SourceLocation ConstructorLParen; - SourceLocation ConstructorRParen; + + /// \brief Source-range of a paren-delimited initializer. + SourceRange DirectInitRange; + + // Was the usage ::new, i.e. is the global new to be used? + bool GlobalNew : 1; + // Do we allocate an array? If so, the first SubExpr is the size expression. + bool Array : 1; + // If this is an array allocation, does the usual deallocation + // function for the allocated type want to know the allocated size? + bool UsualArrayDeleteWantsSize : 1; + // The number of placement new arguments. + unsigned NumPlacementArgs : 13; + // What kind of initializer do we have? Could be none, parens, or braces. + // In storage, we distinguish between "none, and no initializer expr", and + // "none, but an implicit initializer expr". + unsigned StoredInitializationStyle : 2; friend class ASTStmtReader; + friend class ASTStmtWriter; public: + enum InitializationStyle { + NoInit, ///< New-expression has no initializer as written. + CallInit, ///< New-expression has a C++98 paren-delimited initializer. + ListInit ///< New-expression has a C++11 list-initializer. + }; + CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - Expr **placementArgs, unsigned numPlaceArgs, - SourceRange TypeIdParens, - Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, - Expr **constructorArgs, unsigned numConsArgs, - bool HadMultipleCandidates, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, + Expr **placementArgs, unsigned numPlaceArgs, + SourceRange typeIdParens, Expr *arraySize, + InitializationStyle initializationStyle, Expr *initializer, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc, - SourceLocation constructorLParen, - SourceLocation constructorRParen); + SourceLocation startLoc, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, - unsigned numConsArgs); - + bool hasInitializer); + QualType getAllocatedType() const { assert(getType()->isPointerType()); return getType()->getAs<PointerType>()->getPointeeType(); @@ -1130,13 +1498,11 @@ public: /// identical except that the definition of a non-throwing /// exception specification is just "is it throw()?". bool shouldNullCheckAllocation(ASTContext &Ctx) const; - + FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } - CXXConstructorDecl *getConstructor() const { return Constructor; } - void setConstructor(CXXConstructorDecl *D) { Constructor = D; } bool isArray() const { return Array; } Expr *getArraySize() { @@ -1147,97 +1513,87 @@ public: } unsigned getNumPlacementArgs() const { return NumPlacementArgs; } - Expr **getPlacementArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array); + Expr **getPlacementArgs() { + return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); } - + Expr *getPlacementArg(unsigned i) { assert(i < NumPlacementArgs && "Index out of range"); - return cast<Expr>(SubExprs[Array + i]); + return getPlacementArgs()[i]; } const Expr *getPlacementArg(unsigned i) const { assert(i < NumPlacementArgs && "Index out of range"); - return cast<Expr>(SubExprs[Array + i]); + return const_cast<CXXNewExpr*>(this)->getPlacementArg(i); } bool isParenTypeId() const { return TypeIdParens.isValid(); } SourceRange getTypeIdParens() const { return TypeIdParens; } bool isGlobalNew() const { return GlobalNew; } - bool hasInitializer() const { return Initializer; } - /// Answers whether the usual array deallocation function for the - /// allocated type expects the size of the allocation as a - /// parameter. - bool doesUsualArrayDeleteWantSize() const { - return UsualArrayDeleteWantsSize; + /// \brief Whether this new-expression has any initializer at all. + bool hasInitializer() const { return StoredInitializationStyle > 0; } + + /// \brief The kind of initializer this new-expression has. + InitializationStyle getInitializationStyle() const { + if (StoredInitializationStyle == 0) + return NoInit; + return static_cast<InitializationStyle>(StoredInitializationStyle-1); } - unsigned getNumConstructorArgs() const { return NumConstructorArgs; } - - Expr **getConstructorArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs); + /// \brief The initializer of this new-expression. + Expr *getInitializer() { + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; } - - Expr *getConstructorArg(unsigned i) { - assert(i < NumConstructorArgs && "Index out of range"); - return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + const Expr *getInitializer() const { + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; } - const Expr *getConstructorArg(unsigned i) const { - assert(i < NumConstructorArgs && "Index out of range"); - return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + + /// \brief Returns the CXXConstructExpr from this new-expression, or NULL. + const CXXConstructExpr* getConstructExpr() { + return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); } - /// \brief Whether the new expression refers a constructor that was - /// resolved from an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { return HadMultipleCandidates; } - void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } + /// Answers whether the usual array deallocation function for the + /// allocated type expects the size of the allocation as a + /// parameter. + bool doesUsualArrayDeleteWantSize() const { + return UsualArrayDeleteWantsSize; + } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; arg_iterator placement_arg_begin() { - return SubExprs + Array; + return SubExprs + Array + hasInitializer(); } arg_iterator placement_arg_end() { - return SubExprs + Array + getNumPlacementArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array; + return SubExprs + Array + hasInitializer(); } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + getNumPlacementArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } - arg_iterator constructor_arg_begin() { - return SubExprs + Array + getNumPlacementArgs(); - } - arg_iterator constructor_arg_end() { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); - } - const_arg_iterator constructor_arg_begin() const { - return SubExprs + Array + getNumPlacementArgs(); - } - const_arg_iterator constructor_arg_end() const { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); - } - typedef Stmt **raw_arg_iterator; raw_arg_iterator raw_arg_begin() { return SubExprs; } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } const_arg_iterator raw_arg_begin() const { return SubExprs; } - const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } + const_arg_iterator raw_arg_end() const { + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + } SourceLocation getStartLoc() const { return StartLoc; } - SourceLocation getEndLoc() const { return EndLoc; } + SourceLocation getEndLoc() const; - SourceLocation getConstructorLParen() const { return ConstructorLParen; } - SourceLocation getConstructorRParen() const { return ConstructorRParen; } + SourceRange getDirectInitRange() const { return DirectInitRange; } - SourceRange getSourceRange() const { - return SourceRange(StartLoc, EndLoc); + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getStartLoc(), getEndLoc()); } static bool classof(const Stmt *T) { @@ -1247,15 +1603,19 @@ public: // Iterators child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0] + Array + getNumPlacementArgs() - + getNumConstructorArgs()); + return child_range(raw_arg_begin(), raw_arg_end()); } }; /// CXXDeleteExpr - A delete expression for memory deallocation and destructor /// calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { + // Points to the operator delete overload that is used. Could be a member. + FunctionDecl *OperatorDelete; + // The pointer expression to be deleted. + Stmt *Argument; + // Location of the expression. + SourceLocation Loc; // Is this a forced global delete, i.e. "::delete"? bool GlobalDelete : 1; // Is this the array form of delete, i.e. "delete[]"? @@ -1267,12 +1627,6 @@ class CXXDeleteExpr : public Expr { // Does the usual deallocation function for the element type require // a size_t argument? bool UsualArrayDeleteWantsSize : 1; - // Points to the operator delete overload that is used. Could be a member. - FunctionDecl *OperatorDelete; - // The pointer expression to be deleted. - Stmt *Argument; - // Location of the expression. - SourceLocation Loc; public: CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, @@ -1280,10 +1634,10 @@ public: : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, arg->isInstantiationDependent(), arg->containsUnexpandedParameterPack()), + OperatorDelete(operatorDelete), Argument(arg), Loc(loc), GlobalDelete(globalDelete), ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), - OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { } + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } @@ -1308,8 +1662,8 @@ public: /// destroyed is a dependent type which may or may not be a pointer, /// return an invalid type. QualType getDestroyedType() const; - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, Argument->getLocEnd()); } @@ -1324,39 +1678,39 @@ public: friend class ASTStmtReader; }; -/// \brief Structure used to store the type being destroyed by a +/// \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 + /// \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 *>(); + + 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]). /// /// 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 +/// destructor of a scalar type, except that scalar types don't have /// destructors. For example: /// /// \code @@ -1367,7 +1721,7 @@ public: /// \endcode /// /// Pseudo-destructors typically occur when instantiating templates such as: -/// +/// /// \code /// template<typename T> /// void destroy(T* ptr) { @@ -1387,27 +1741,27 @@ class CXXPseudoDestructorExpr : public Expr { /// \brief The location of the '.' or '->' operator. SourceLocation OperatorLoc; - + /// \brief The nested-name-specifier that follows the operator, if present. NestedNameSpecifierLoc QualifierLoc; /// \brief The type that precedes the '::' in a qualified pseudo-destructor /// expression. TypeSourceInfo *ScopeType; - - /// \brief The location of the '::' in a qualified pseudo-destructor + + /// \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 + + /// \brief The type being destroyed, or its name if we were unable to /// resolve the name. PseudoDestructorTypeStorage DestroyedType; friend class ASTStmtReader; - + public: CXXPseudoDestructorExpr(ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, @@ -1431,12 +1785,12 @@ public: /// \brief Retrieves the nested-name-specifier that qualifies the type name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - + /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } /// \brief Determine whether this pseudo-destructor expression was written @@ -1446,48 +1800,48 @@ public: /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieve the scope type in a qualified pseudo-destructor + /// \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 + /// \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 + /// 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(); + 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(); + SourceLocation getDestroyedTypeLoc() const { + return DestroyedType.getLocation(); } /// \brief Set the name of destroyed type for a dependent pseudo-destructor @@ -1501,7 +1855,7 @@ public: DestroyedType = PseudoDestructorTypeStorage(Info); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; @@ -1533,7 +1887,7 @@ class UnaryTypeTraitExpr : public Expr { TypeSourceInfo *QueriedType; public: - UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, + UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, TypeSourceInfo *queried, bool value, SourceLocation rparen, QualType ty) : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, @@ -1546,14 +1900,14 @@ public: : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false), QueriedType() { } - SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen);} UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); } QualType getQueriedType() const { return QueriedType->getType(); } TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } - + bool getValue() const { return Value; } static bool classof(const Stmt *T) { @@ -1591,10 +1945,10 @@ class BinaryTypeTraitExpr : public Expr { TypeSourceInfo *RhsType; public: - BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, - TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, + BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, + TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, bool value, SourceLocation rparen, QualType ty) - : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, + : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, lhsType->getType()->isDependentType() || rhsType->getType()->isDependentType(), (lhsType->getType()->isInstantiationDependentType() || @@ -1609,7 +1963,7 @@ public: : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false), LhsType(), RhsType() { } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen); } @@ -1622,7 +1976,7 @@ public: TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; } TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; } - + bool getValue() const { assert(!isTypeDependent()); return Value; } static bool classof(const Stmt *T) { @@ -1636,12 +1990,110 @@ public: friend class ASTStmtReader; }; +/// \brief A type trait used in the implementation of various C++11 and +/// Library TR1 trait templates. +/// +/// \code +/// __is_trivially_constructible(vector<int>, int*, int*) +/// \endcode +class TypeTraitExpr : public Expr { + /// \brief The location of the type trait keyword. + SourceLocation Loc; + + /// \brief The location of the closing parenthesis. + SourceLocation RParenLoc; + + // Note: The TypeSourceInfos for the arguments are allocated after the + // TypeTraitExpr. + + TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value); + + TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } + + /// \brief Retrieve the argument types. + TypeSourceInfo **getTypeSourceInfos() { + return reinterpret_cast<TypeSourceInfo **>(this+1); + } + + /// \brief Retrieve the argument types. + TypeSourceInfo * const *getTypeSourceInfos() const { + return reinterpret_cast<TypeSourceInfo * const*>(this+1); + } + +public: + /// \brief Create a new type trait expression. + static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, + TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value); + + static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs); + + /// \brief Determine which type trait this expression uses. + TypeTrait getTrait() const { + return static_cast<TypeTrait>(TypeTraitExprBits.Kind); + } + + bool getValue() const { + assert(!isValueDependent()); + return TypeTraitExprBits.Value; + } + + /// \brief Determine the number of arguments to this type trait. + unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } + + /// \brief Retrieve the Ith argument. + TypeSourceInfo *getArg(unsigned I) const { + assert(I < getNumArgs() && "Argument out-of-range"); + return getArgs()[I]; + } + + /// \brief Retrieve the argument types. + ArrayRef<TypeSourceInfo *> getArgs() const { + return ArrayRef<TypeSourceInfo *>(getTypeSourceInfos(), getNumArgs()); + } + + typedef TypeSourceInfo **arg_iterator; + arg_iterator arg_begin() { + return getTypeSourceInfos(); + } + arg_iterator arg_end() { + return getTypeSourceInfos() + getNumArgs(); + } + + typedef TypeSourceInfo const * const *arg_const_iterator; + arg_const_iterator arg_begin() const { return getTypeSourceInfos(); } + arg_const_iterator arg_end() const { + return getTypeSourceInfos() + getNumArgs(); + } + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParenLoc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == TypeTraitExprClass; + } + static bool classof(const TypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +}; + /// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the /// implementation of __array_rank and __array_extent. /// Example: /// __array_rank(int[10][20]) == 2 /// __array_extent(int, 1) == 20 class ArrayTypeTraitExpr : public Expr { + virtual void anchor(); + /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. unsigned ATT : 2; @@ -1679,7 +2131,9 @@ public: virtual ~ArrayTypeTraitExpr() { } - virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen); } + virtual SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(Loc, RParen); + } ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } @@ -1720,7 +2174,7 @@ class ExpressionTraitExpr : public Expr { Expr* QueriedExpression; public: - ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried, bool value, SourceLocation rparen, QualType resultType) : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, @@ -1729,13 +2183,14 @@ public: queried->isTypeDependent(), queried->isInstantiationDependent(), queried->containsUnexpandedParameterPack()), - ET(et), Value(value), Loc(loc), RParen(rparen), QueriedExpression(queried) { } + ET(et), Value(value), Loc(loc), RParen(rparen), + QueriedExpression(queried) { } explicit ExpressionTraitExpr(EmptyShell Empty) : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), QueriedExpression() { } - SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen);} ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } @@ -1758,6 +2213,12 @@ public: /// \brief A reference to an overloaded function set, either an /// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. class OverloadExpr : public Expr { + /// The common name of these declarations. + DeclarationNameInfo NameInfo; + + /// \brief The nested-name-specifier that qualifies the name, if any. + NestedNameSpecifierLoc QualifierLoc; + /// The results. These are undesugared, which is to say, they may /// include UsingShadowDecls. Access is relative to the naming /// class. @@ -1765,18 +2226,22 @@ class OverloadExpr : public Expr { DeclAccessPair *Results; unsigned NumResults; - /// The common name of these declarations. - DeclarationNameInfo NameInfo; +protected: + /// \brief Whether the name includes info for explicit template + /// keyword and arguments. + bool HasTemplateKWAndArgsInfo; - /// \brief The nested-name-specifier that qualifies the name, if any. - NestedNameSpecifierLoc QualifierLoc; + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo(); // defined far below. -protected: - /// True if the name was a template-id. - bool HasExplicitTemplateArgs; + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<OverloadExpr*>(this)->getTemplateKWAndArgsInfo(); + } OverloadExpr(StmtClass K, ASTContext &C, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, @@ -1785,8 +2250,8 @@ protected: bool KnownContainsUnexpandedParameterPack); OverloadExpr(StmtClass K, EmptyShell Empty) - : Expr(K, Empty), Results(0), NumResults(0), - QualifierLoc(), HasExplicitTemplateArgs(false) { } + : Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0), + HasTemplateKWAndArgsInfo(false) { } void initializeResults(ASTContext &C, UnresolvedSetIterator Begin, @@ -1832,10 +2297,10 @@ public: typedef UnresolvedSetImpl::iterator decls_iterator; decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } - decls_iterator decls_end() const { + decls_iterator decls_end() const { return UnresolvedSetIterator(Results + NumResults); } - + /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } @@ -1849,24 +2314,67 @@ public: SourceLocation getNameLoc() const { return NameInfo.getLoc(); } /// Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } - /// Fetches the nested-name qualifier with source-location information, if + /// Fetches the nested-name qualifier with source-location information, if /// one was given. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Determines whether this expression had an explicit - /// template argument list, e.g. f<int>. - bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + /// \brief Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// Determines whether the name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// Determines whether this expression had explicit template arguments. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs(); // defined far below + ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *getTemplateKWAndArgsInfo(); + } const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); } + TemplateArgumentLoc const *getTemplateArgs() const { + return getExplicitTemplateArgs().getTemplateArgs(); + } + + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs().NumTemplateArgs; + } + + /// Copies the template arguments into the given structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs().copyInto(List); + } + /// \brief Retrieves the optional explicit template arguments. /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. @@ -1916,16 +2424,17 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(ASTContext &C, + UnresolvedLookupExpr(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, + bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool StdIsAssociatedNamespace) - : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, NameInfo, - TemplateArgs, Begin, End, false, false, false), + : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, + NameInfo, TemplateArgs, Begin, End, false, false, false), RequiresADL(RequiresADL), StdIsAssociatedNamespace(StdIsAssociatedNamespace), Overloaded(Overloaded), NamingClass(NamingClass) @@ -1938,19 +2447,20 @@ class UnresolvedLookupExpr : public OverloadExpr { {} friend class ASTStmtReader; - + public: static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, - UnresolvedSetIterator Begin, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool StdIsAssociatedNamespace = false) { assert((ADL || !StdIsAssociatedNamespace) && "std considered associated namespace when not performing ADL"); - return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, + return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, + SourceLocation(), NameInfo, ADL, Overloaded, 0, Begin, End, StdIsAssociatedNamespace); } @@ -1958,14 +2468,15 @@ public: static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool ADL, - const TemplateArgumentListInfo &Args, - UnresolvedSetIterator Begin, + const TemplateArgumentListInfo *Args, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); static UnresolvedLookupExpr *CreateEmpty(ASTContext &C, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// True if this declaration should be extended by @@ -1984,56 +2495,11 @@ public: /// that was looked in to find these results. CXXRecordDecl *getNamingClass() const { return NamingClass; } - // Note that, inconsistently with the explicit-template-argument AST - // nodes, users are *forbidden* from calling these methods on objects - // without explicit template arguments. - - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1); - } - - /// Gets a reference to the explicit template argument list. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1); - } - - /// \brief Retrieves the optional explicit template arguments. - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { - if (!hasExplicitTemplateArgs()) return 0; - return &getExplicitTemplateArgs(); - } - - /// \brief Copies the template arguments (if present) into the given - /// structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - SourceLocation getLAngleLoc() const { - return getExplicitTemplateArgs().LAngleLoc; - } - - SourceLocation getRAngleLoc() const { - return getExplicitTemplateArgs().RAngleLoc; - } - - TemplateArgumentLoc const *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); - } - - unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; - } - - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { SourceRange Range(getNameInfo().getSourceRange()); - if (getQualifierLoc()) + if (getQualifierLoc()) Range.setBegin(getQualifierLoc().getBeginLoc()); - if (hasExplicitTemplateArgs()) + if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; } @@ -2064,26 +2530,40 @@ class DependentScopeDeclRefExpr : public Expr { /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; - + /// The name of the entity we will be referencing. DeclarationNameInfo NameInfo; - /// \brief Whether the name includes explicit template arguments. - bool HasExplicitTemplateArgs; + /// \brief Whether the name includes info for explicit template + /// keyword and arguments. + bool HasTemplateKWAndArgsInfo; + + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) return 0; + return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); + } + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<DependentScopeDeclRefExpr*>(this) + ->getTemplateKWAndArgsInfo(); + } DependentScopeDeclRefExpr(QualType T, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args); public: static DependentScopeDeclRefExpr *Create(ASTContext &C, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs = 0); + const TemplateArgumentListInfo *TemplateArgs); static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// \brief Retrieve the name that this expression refers to. @@ -2098,16 +2578,40 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies the /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - + + /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } + /// \brief Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// Determines whether the name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + /// Determines whether this lookup had explicit template arguments. - bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } // Note that, inconsistently with the explicit-template-argument AST // nodes, users are *forbidden* from calling these methods on objects @@ -2137,14 +2641,6 @@ public: void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { getExplicitTemplateArgs().copyInto(List); } - - SourceLocation getLAngleLoc() const { - return getExplicitTemplateArgs().LAngleLoc; - } - - SourceLocation getRAngleLoc() const { - return getExplicitTemplateArgs().RAngleLoc; - } TemplateArgumentLoc const *getTemplateArgs() const { return getExplicitTemplateArgs().getTemplateArgs(); @@ -2154,7 +2650,7 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { SourceRange Range(QualifierLoc.getBeginLoc(), getLocation()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); @@ -2175,46 +2671,61 @@ public: /// Represents an expression --- generally a full-expression --- which /// introduces cleanups to be run at the end of the sub-expression's /// evaluation. The most common source of expression-introduced -/// cleanups is temporary objects in C++, but several other C++ -/// expressions can create cleanups. +/// cleanups is temporary objects in C++, but several other kinds of +/// expressions can create cleanups, including basically every +/// call in ARC that returns an Objective-C pointer. +/// +/// This expression also tracks whether the sub-expression contains a +/// potentially-evaluated block literal. The lifetime of a block +/// literal is the extent of the enclosing scope. class ExprWithCleanups : public Expr { +public: + /// The type of objects that are kept in the cleanup. + /// It's useful to remember the set of blocks; we could also + /// remember the set of temporaries, but there's currently + /// no need. + typedef BlockDecl *CleanupObject; + +private: Stmt *SubExpr; - CXXTemporary **Temps; - unsigned NumTemps; + ExprWithCleanups(EmptyShell, unsigned NumObjects); + ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects); - ExprWithCleanups(ASTContext &C, Expr *SubExpr, - CXXTemporary **Temps, unsigned NumTemps); - -public: - ExprWithCleanups(EmptyShell Empty) - : Expr(ExprWithCleanupsClass, Empty), - SubExpr(0), Temps(0), NumTemps(0) {} - - static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr, - CXXTemporary **Temps, - unsigned NumTemps); - - unsigned getNumTemporaries() const { return NumTemps; } - void setNumTemporaries(ASTContext &C, unsigned N); - - CXXTemporary *getTemporary(unsigned i) { - assert(i < NumTemps && "Index out of range"); - return Temps[i]; + CleanupObject *getObjectsBuffer() { + return reinterpret_cast<CleanupObject*>(this + 1); + } + const CleanupObject *getObjectsBuffer() const { + return reinterpret_cast<const CleanupObject*>(this + 1); } - const CXXTemporary *getTemporary(unsigned i) const { - return const_cast<ExprWithCleanups*>(this)->getTemporary(i); + friend class ASTStmtReader; + +public: + static ExprWithCleanups *Create(ASTContext &C, EmptyShell empty, + unsigned numObjects); + + static ExprWithCleanups *Create(ASTContext &C, Expr *subexpr, + ArrayRef<CleanupObject> objects); + + ArrayRef<CleanupObject> getObjects() const { + return ArrayRef<CleanupObject>(getObjectsBuffer(), getNumObjects()); } - void setTemporary(unsigned i, CXXTemporary *T) { - assert(i < NumTemps && "Index out of range"); - Temps[i] = T; + + unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } + + CleanupObject getObject(unsigned i) const { + assert(i < getNumObjects() && "Index out of range"); + return getObjects()[i]; } Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + + /// setSubExpr - As with any mutator of the AST, be very careful + /// when modifying an existing AST to preserve its invariants. void setSubExpr(Expr *E) { SubExpr = E; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SubExpr->getSourceRange(); } @@ -2252,7 +2763,7 @@ public: class CXXUnresolvedConstructExpr : public Expr { /// \brief The type being constructed. TypeSourceInfo *Type; - + /// \brief The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -2272,7 +2783,7 @@ class CXXUnresolvedConstructExpr : public Expr { : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { } friend class ASTStmtReader; - + public: static CXXUnresolvedConstructExpr *Create(ASTContext &C, TypeSourceInfo *Type, @@ -2288,10 +2799,10 @@ public: /// in the source code. QualType getTypeAsWritten() const { return Type->getType(); } - /// \brief Retrieve the type source information for the type being + /// \brief Retrieve the type source information for the type being /// constructed. TypeSourceInfo *getTypeSourceInfo() const { return Type; } - + /// \brief Retrieve the location of the left parentheses ('(') that /// precedes the argument list. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -2332,8 +2843,8 @@ public: *(arg_begin() + I) = E; } - SourceRange getSourceRange() const; - + SourceRange getSourceRange() const LLVM_READONLY; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedConstructExprClass; } @@ -2366,9 +2877,9 @@ class CXXDependentScopeMemberExpr : public Expr { /// the '.' operator. bool IsArrow : 1; - /// \brief Whether this member expression has explicitly-specified template - /// arguments. - bool HasExplicitTemplateArgs : 1; + /// \brief Whether this member expression has info for explicit template + /// keyword and arguments. + bool HasTemplateKWAndArgsInfo : 1; /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; @@ -2390,10 +2901,22 @@ class CXXDependentScopeMemberExpr : public Expr { /// FIXME: could also be a template-id DeclarationNameInfo MemberNameInfo; + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) return 0; + return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); + } + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<CXXDependentScopeMemberExpr*>(this) + ->getTemplateKWAndArgsInfo(); + } + CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2412,12 +2935,13 @@ public: Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * - CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// \brief True if this is an implicit access, i.e. one in which the @@ -2443,15 +2967,15 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } /// \brief Retrieve the nested-name-specifier that qualifies the member /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - + + /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. @@ -2481,16 +3005,38 @@ public: // expression refers to. SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } + /// \brief Retrieve the location of the template keyword preceding the + /// member name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the member name, if any. + SourceLocation getLAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the member name, if any. + SourceLocation getRAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// Determines whether the member name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgs() const { - return HasExplicitTemplateArgs; - } + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(HasExplicitTemplateArgs); + assert(hasExplicitTemplateArgs()); return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); } @@ -2520,12 +3066,6 @@ public: getExplicitTemplateArgs().initializeFrom(List); } - /// \brief Retrieve the location of the left angle bracket following the - /// member name ('<'), if any. - SourceLocation getLAngleLoc() const { - return getExplicitTemplateArgs().LAngleLoc; - } - /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { @@ -2538,13 +3078,7 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { - return getExplicitTemplateArgs().RAngleLoc; - } - - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { SourceRange Range; if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); @@ -2612,28 +3146,30 @@ class UnresolvedMemberExpr : public OverloadExpr { Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); - + UnresolvedMemberExpr(EmptyShell Empty) : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(0) { } friend class ASTStmtReader; - + public: static UnresolvedMemberExpr * Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); static UnresolvedMemberExpr * - CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// \brief True if this is an implicit access, i.e. one in which the @@ -2680,58 +3216,7 @@ public: // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<const ASTTemplateArgumentListInfo *>(this + 1); - } - - /// \brief Retrieves the optional explicit template arguments. - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { - if (!hasExplicitTemplateArgs()) return 0; - return &getExplicitTemplateArgs(); - } - - /// \brief Copies the template arguments into the given structure. - void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Retrieve the location of the left angle bracket following - /// the member name ('<'). - SourceLocation getLAngleLoc() const { - return getExplicitTemplateArgs().LAngleLoc; - } - - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); - } - - /// \brief Retrieve the number of template arguments provided as - /// part of this template-id. - unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; - } - - /// \brief Retrieve the location of the right angle bracket - /// following the template arguments ('>'). - SourceLocation getRAngleLoc() const { - return getExplicitTemplateArgs().RAngleLoc; - } - - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); @@ -2783,7 +3268,7 @@ public: Expr *getOperand() const { return static_cast<Expr*>(Operand); } - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } bool getValue() const { return Value; } @@ -2796,7 +3281,7 @@ public: child_range children() { return child_range(&Operand, &Operand + 1); } }; -/// \brief Represents a C++0x pack expansion that produces a sequence of +/// \brief Represents a C++0x pack expansion that produces a sequence of /// expressions. /// /// A pack expansion expression contains a pattern (which itself is an @@ -2810,29 +3295,29 @@ public: /// \endcode /// /// Here, the argument to the function object \c f is a pack expansion whose -/// pattern is \c static_cast<Types&&>(args). When the \c forward function +/// pattern is \c static_cast<Types&&>(args). When the \c forward function /// template is instantiated, the pack expansion will instantiate to zero or /// or more function arguments to the function object \c f. class PackExpansionExpr : public Expr { SourceLocation EllipsisLoc; - + /// \brief The number of expansions that will be produced by this pack /// expansion expression, if known. /// /// When zero, the number of expansions is not known. Otherwise, this value /// is the number of expansions + 1. unsigned NumExpansions; - + Stmt *Pattern; - + friend class ASTStmtReader; friend class ASTStmtWriter; - + public: PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, llvm::Optional<unsigned> NumExpansions) - : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), - Pattern->getObjectKind(), /*TypeDependent=*/true, + : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), + Pattern->getObjectKind(), /*TypeDependent=*/true, /*ValueDependent=*/true, /*InstantiationDependent=*/true, /*ContainsUnexpandedParameterPack=*/false), EllipsisLoc(EllipsisLoc), @@ -2840,7 +3325,7 @@ public: Pattern(Pattern) { } PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { } - + /// \brief Retrieve the pattern of the pack expansion. Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); } @@ -2850,17 +3335,17 @@ public: /// \brief Retrieve the location of the ellipsis that describes this pack /// expansion. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - - /// \brief Determine the number of expansions that will be produced when + + /// \brief Determine the number of expansions that will be produced when /// this pack expansion is instantiated, if already known. llvm::Optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - + return llvm::Optional<unsigned>(); } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Pattern->getLocStart(), EllipsisLoc); } @@ -2868,21 +3353,24 @@ public: return T->getStmtClass() == PackExpansionExprClass; } static bool classof(const PackExpansionExpr *) { return true; } - + // Iterators child_range children() { return child_range(&Pattern, &Pattern + 1); } }; - -inline ASTTemplateArgumentListInfo &OverloadExpr::getExplicitTemplateArgs() { + +inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) return 0; if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs(); + return reinterpret_cast<ASTTemplateKWAndArgsInfo*> + (cast<UnresolvedLookupExpr>(this) + 1); else - return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs(); + return reinterpret_cast<ASTTemplateKWAndArgsInfo*> + (cast<UnresolvedMemberExpr>(this) + 1); } -/// \brief Represents an expression that computes the length of a parameter +/// \brief Represents an expression that computes the length of a parameter /// pack. /// /// \code @@ -2894,30 +3382,30 @@ inline ASTTemplateArgumentListInfo &OverloadExpr::getExplicitTemplateArgs() { class SizeOfPackExpr : public Expr { /// \brief The location of the 'sizeof' keyword. SourceLocation OperatorLoc; - + /// \brief The location of the name of the parameter pack. SourceLocation PackLoc; - + /// \brief The location of the closing parenthesis. SourceLocation RParenLoc; - + /// \brief The length of the parameter pack, if known. /// /// When this expression is value-dependent, the length of the parameter pack /// is unknown. When this expression is not value-dependent, the length is /// known. unsigned Length; - + /// \brief The parameter pack itself. NamedDecl *Pack; - + friend class ASTStmtReader; friend class ASTStmtWriter; - + public: /// \brief Creates a value-dependent expression that computes the length of /// the given parameter pack. - SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, + SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc) : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, /*TypeDependent=*/false, /*ValueDependent=*/true, @@ -2928,7 +3416,7 @@ public: /// \brief Creates an expression that computes the length of /// the given parameter pack, which is already known. - SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, + SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, unsigned Length) : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, @@ -2940,38 +3428,38 @@ public: /// \brief Create an empty expression. SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { } - + /// \brief Determine the location of the 'sizeof' keyword. SourceLocation getOperatorLoc() const { return OperatorLoc; } /// \brief Determine the location of the parameter pack. SourceLocation getPackLoc() const { return PackLoc; } - + /// \brief Determine the location of the right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - + /// \brief Retrieve the parameter pack. NamedDecl *getPack() const { return Pack; } - + /// \brief Retrieve the length of the parameter pack. /// - /// This routine may only be invoked when the expression is not + /// This routine may only be invoked when the expression is not /// value-dependent. unsigned getPackLength() const { - assert(!isValueDependent() && + assert(!isValueDependent() && "Cannot get the length of a value-dependent pack size expression"); return Length; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(OperatorLoc, RParenLoc); } - + static bool classof(const Stmt *T) { return T->getStmtClass() == SizeOfPackExprClass; } static bool classof(const SizeOfPackExpr *) { return true; } - + // Iterators child_range children() { return child_range(); } }; @@ -2990,11 +3478,11 @@ class SubstNonTypeTemplateParmExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) + explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) : Expr(SubstNonTypeTemplateParmExprClass, Empty) { } public: - SubstNonTypeTemplateParmExpr(QualType type, + SubstNonTypeTemplateParmExpr(QualType type, ExprValueKind valueKind, SourceLocation loc, NonTypeTemplateParmDecl *param, @@ -3006,19 +3494,19 @@ public: Param(param), Replacement(replacement), NameLoc(loc) {} SourceLocation getNameLoc() const { return NameLoc; } - SourceRange getSourceRange() const { return NameLoc; } + SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } Expr *getReplacement() const { return cast<Expr>(Replacement); } - + NonTypeTemplateParmDecl *getParameter() const { return Param; } static bool classof(const Stmt *s) { return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; } - static bool classof(const SubstNonTypeTemplateParmExpr *) { - return true; + static bool classof(const SubstNonTypeTemplateParmExpr *) { + return true; } - + // Iterators child_range children() { return child_range(&Replacement, &Replacement+1); } }; @@ -3028,7 +3516,7 @@ public: /// /// When a pack expansion in the source code contains multiple parameter packs /// and those parameter packs correspond to different levels of template -/// parameter lists, this node node is used to represent a non-type template +/// parameter lists, this node node is used to represent a non-type template /// parameter pack from an outer level, which has already had its argument pack /// substituted but that still lives within a pack expansion that itself /// could not be instantiated. When actually performing a substitution into @@ -3038,47 +3526,47 @@ public: class SubstNonTypeTemplateParmPackExpr : public Expr { /// \brief The non-type template parameter pack itself. NonTypeTemplateParmDecl *Param; - + /// \brief A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - + /// \brief The number of template arguments in \c Arguments. unsigned NumArguments; - + /// \brief The location of the non-type template parameter pack reference. SourceLocation NameLoc; - + friend class ASTReader; friend class ASTStmtReader; - explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) + explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } - + public: - SubstNonTypeTemplateParmPackExpr(QualType T, + SubstNonTypeTemplateParmPackExpr(QualType T, NonTypeTemplateParmDecl *Param, SourceLocation NameLoc, const TemplateArgument &ArgPack); - + /// \brief Retrieve the non-type template parameter pack being substituted. NonTypeTemplateParmDecl *getParameterPack() const { return Param; } /// \brief Retrieve the location of the parameter pack name. SourceLocation getParameterPackLocation() const { return NameLoc; } - + /// \brief Retrieve the template argument pack containing the substituted /// template arguments. TemplateArgument getArgumentPack() const; - SourceRange getSourceRange() const { return NameLoc; } - + SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } + static bool classof(const Stmt *T) { return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; } - static bool classof(const SubstNonTypeTemplateParmPackExpr *) { - return true; + static bool classof(const SubstNonTypeTemplateParmPackExpr *) { + return true; } - + // Iterators child_range children() { return child_range(); } }; @@ -3102,13 +3590,13 @@ public: class MaterializeTemporaryExpr : public Expr { /// \brief The temporary-generating expression whose value will be /// materialized. - Stmt *Temporary; - + Stmt *Temporary; + friend class ASTStmtReader; friend class ASTStmtWriter; - + public: - MaterializeTemporaryExpr(QualType T, Expr *Temporary, + MaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference) : Expr(MaterializeTemporaryExprClass, T, BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, @@ -3116,33 +3604,35 @@ public: Temporary->isInstantiationDependent(), Temporary->containsUnexpandedParameterPack()), Temporary(Temporary) { } - - MaterializeTemporaryExpr(EmptyShell Empty) + + MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) { } - + /// \brief Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. Expr *GetTemporaryExpr() const { return reinterpret_cast<Expr *>(Temporary); } - + /// \brief Determine whether this materialized temporary is bound to an /// lvalue reference; otherwise, it's bound to an rvalue reference. - bool isBoundToLvalueReference() const { + bool isBoundToLvalueReference() const { return getValueKind() == VK_LValue; } - - SourceRange getSourceRange() const { return Temporary->getSourceRange(); } - + + SourceRange getSourceRange() const LLVM_READONLY { + return Temporary->getSourceRange(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MaterializeTemporaryExprClass; } - static bool classof(const MaterializeTemporaryExpr *) { - return true; + static bool classof(const MaterializeTemporaryExpr *) { + return true; } - + // Iterators child_range children() { return child_range(&Temporary, &Temporary + 1); } }; - + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h index 55726eb..4bfd12c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/SelectorLocationsKind.h" #include "clang/Basic/IdentifierTable.h" +#include "llvm/Support/Compiler.h" namespace clang { class IdentifierInfo; @@ -43,7 +44,7 @@ public: SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, String->getLocEnd()); } @@ -56,6 +57,281 @@ public: child_range children() { return child_range(&String, &String+1); } }; +/// ObjCBoolLiteralExpr - Objective-C Boolean Literal. +/// +class ObjCBoolLiteralExpr : public Expr { + bool Value; + SourceLocation Loc; +public: + ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : + Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + false, false), Value(val), Loc(l) {} + + explicit ObjCBoolLiteralExpr(EmptyShell Empty) + : Expr(ObjCBoolLiteralExprClass, Empty) { } + + bool getValue() const { return Value; } + void setValue(bool V) { Value = V; } + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBoolLiteralExprClass; + } + static bool classof(const ObjCBoolLiteralExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } +}; + +/// ObjCNumericLiteral - used for objective-c numeric literals; +/// as in: @42 or @true (c++/objc++) or @__yes (c/objc) +class ObjCNumericLiteral : public Expr { + /// Number - expression AST node for the numeric literal + Stmt *Number; + ObjCMethodDecl *ObjCNumericLiteralMethod; + SourceLocation AtLoc; +public: + ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method, + SourceLocation L) + : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary, + false, false, false, false), Number(NL), + ObjCNumericLiteralMethod(method), AtLoc(L) {} + explicit ObjCNumericLiteral(EmptyShell Empty) + : Expr(ObjCNumericLiteralClass, Empty) {} + + Expr *getNumber() { return cast<Expr>(Number); } + const Expr *getNumber() const { return cast<Expr>(Number); } + + ObjCMethodDecl *getObjCNumericLiteralMethod() const { + return ObjCNumericLiteralMethod; + } + + SourceLocation getAtLoc() const { return AtLoc; } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(AtLoc, Number->getSourceRange().getEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCNumericLiteralClass; + } + static bool classof(const ObjCNumericLiteral *) { return true; } + + // Iterators + child_range children() { return child_range(&Number, &Number+1); } + + friend class ASTStmtReader; +}; + +/// ObjCArrayLiteral - used for objective-c array containers; as in: +/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]]; +class ObjCArrayLiteral : public Expr { + unsigned NumElements; + SourceRange Range; + ObjCMethodDecl *ArrayWithObjectsMethod; + + ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl * Method, + SourceRange SR); + + explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements) + : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} + +public: + static ObjCArrayLiteral *Create(ASTContext &C, + llvm::ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl * Method, + SourceRange SR); + + static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements); + + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCArrayLiteralClass; + } + static bool classof(const ObjCArrayLiteral *) { return true; } + + /// \brief Retrieve elements of array of literals. + Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); } + + /// \brief Retrieve elements of array of literals. + const Expr * const *getElements() const { + return reinterpret_cast<const Expr * const*>(this + 1); + } + + /// getNumElements - Return number of elements of objective-c array literal. + unsigned getNumElements() const { return NumElements; } + + /// getExpr - Return the Expr at the specified index. + Expr *getElement(unsigned Index) { + assert((Index < NumElements) && "Arg access out of range!"); + return cast<Expr>(getElements()[Index]); + } + const Expr *getElement(unsigned Index) const { + assert((Index < NumElements) && "Arg access out of range!"); + return cast<Expr>(getElements()[Index]); + } + + ObjCMethodDecl *getArrayWithObjectsMethod() const { + return ArrayWithObjectsMethod; + } + + // Iterators + child_range children() { + return child_range((Stmt **)getElements(), + (Stmt **)getElements() + NumElements); + } + + friend class ASTStmtReader; +}; + +/// \brief An element in an Objective-C dictionary literal. +/// +struct ObjCDictionaryElement { + /// \brief The key for the dictionary element. + Expr *Key; + + /// \brief The value of the dictionary element. + Expr *Value; + + /// \brief The location of the ellipsis, if this is a pack expansion. + SourceLocation EllipsisLoc; + + /// \brief The number of elements this pack expansion will expand to, if + /// this is a pack expansion and is known. + llvm::Optional<unsigned> NumExpansions; + + /// \brief Determines whether this dictionary element is a pack expansion. + bool isPackExpansion() const { return EllipsisLoc.isValid(); } +}; + +/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary +/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; +class ObjCDictionaryLiteral : public Expr { + /// \brief Key/value pair used to store the key and value of a given element. + /// + /// Objects of this type are stored directly after the expression. + struct KeyValuePair { + Expr *Key; + Expr *Value; + }; + + /// \brief Data that describes an element that is a pack expansion, used if any + /// of the elements in the dictionary literal are pack expansions. + struct ExpansionData { + /// \brief The location of the ellipsis, if this element is a pack + /// expansion. + SourceLocation EllipsisLoc; + + /// \brief If non-zero, the number of elements that this pack + /// expansion will expand to (+1). + unsigned NumExpansionsPlusOne; + }; + + /// \brief The number of elements in this dictionary literal. + unsigned NumElements : 31; + + /// \brief Determine whether this dictionary literal has any pack expansions. + /// + /// If the dictionary literal has pack expansions, then there will + /// be an array of pack expansion data following the array of + /// key/value pairs, which provide the locations of the ellipses (if + /// any) and number of elements in the expansion (if known). If + /// there are no pack expansions, we optimize away this storage. + unsigned HasPackExpansions : 1; + + SourceRange Range; + ObjCMethodDecl *DictWithObjectsMethod; + + ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, + QualType T, ObjCMethodDecl *method, + SourceRange SR); + + explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements, + bool HasPackExpansions) + : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements), + HasPackExpansions(HasPackExpansions) {} + + KeyValuePair *getKeyValues() { + return reinterpret_cast<KeyValuePair *>(this + 1); + } + + const KeyValuePair *getKeyValues() const { + return reinterpret_cast<const KeyValuePair *>(this + 1); + } + + ExpansionData *getExpansionData() { + if (!HasPackExpansions) + return 0; + + return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements); + } + + const ExpansionData *getExpansionData() const { + if (!HasPackExpansions) + return 0; + + return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements); + } + +public: + static ObjCDictionaryLiteral *Create(ASTContext &C, + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, + QualType T, ObjCMethodDecl *method, + SourceRange SR); + + static ObjCDictionaryLiteral *CreateEmpty(ASTContext &C, + unsigned NumElements, + bool HasPackExpansions); + + /// getNumElements - Return number of elements of objective-c dictionary + /// literal. + unsigned getNumElements() const { return NumElements; } + + ObjCDictionaryElement getKeyValueElement(unsigned Index) const { + assert((Index < NumElements) && "Arg access out of range!"); + const KeyValuePair &KV = getKeyValues()[Index]; + ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), + llvm::Optional<unsigned>() }; + if (HasPackExpansions) { + const ExpansionData &Expansion = getExpansionData()[Index]; + Result.EllipsisLoc = Expansion.EllipsisLoc; + if (Expansion.NumExpansionsPlusOne > 0) + Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1; + } + return Result; + } + + ObjCMethodDecl *getDictWithObjectsMethod() const + { return DictWithObjectsMethod; } + + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCDictionaryLiteralClass; + } + static bool classof(const ObjCDictionaryLiteral *) { return true; } + + // Iterators + child_range children() { + // Note: we're taking advantage of the layout of the KeyValuePair struct + // here. If that struct changes, this code will need to change as well. + return child_range(reinterpret_cast<Stmt **>(this + 1), + reinterpret_cast<Stmt **>(this + 1) + NumElements * 2); + } + + friend class ASTStmtReader; + friend class ASTStmtWriter; +}; + + /// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type /// and behavior as StringLiteral except that the string initializer is obtained /// from ASTContext with the encoding type as an argument. @@ -87,7 +363,7 @@ public: EncodedType = EncType; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, RParenLoc); } @@ -121,7 +397,7 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, RParenLoc); } @@ -161,7 +437,7 @@ public: void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, RParenLoc); } @@ -176,9 +452,9 @@ public: /// ObjCIvarRefExpr - A reference to an ObjC instance variable. class ObjCIvarRefExpr : public Expr { - class ObjCIvarDecl *D; - SourceLocation Loc; + ObjCIvarDecl *D; Stmt *Base; + SourceLocation Loc; bool IsArrow:1; // True if this is "X->F", false if this is "X.F". bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). @@ -190,7 +466,7 @@ public: /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} + D(d), Base(base), Loc(l), IsArrow(arrow), IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -211,7 +487,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return isFreeIvar() ? SourceRange(Loc) : SourceRange(getBase()->getLocStart(), Loc); } @@ -227,7 +503,6 @@ public: /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC /// property. -/// class ObjCPropertyRefExpr : public Expr { private: /// If the bool is true, this is an implicit property reference; the @@ -235,7 +510,23 @@ private: /// if the bool is false, this is an explicit property reference; /// the pointer is an ObjCPropertyDecl and Setter is always null. llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter; - ObjCMethodDecl *Setter; + + /// \brief Indicates whether the property reference will result in a message + /// to the getter, the setter, or both. + /// This applies to both implicit and explicit property references. + enum MethodRefFlags { + MethodRef_None = 0, + MethodRef_Getter = 0x1, + MethodRef_Setter = 0x2 + }; + + /// \brief Contains the Setter method pointer and MethodRefFlags bit flags. + llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags; + + // FIXME: Maybe we should store the property identifier here, + // because it's not rederivable from the other data when there's an + // implicit property with no getter (because the 'foo' -> 'setFoo:' + // transformation is lossy on the first character). SourceLocation IdLoc; @@ -253,8 +544,9 @@ public: /*TypeDependent=*/false, base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), Setter(0), + PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), IdLoc(l), ReceiverLoc(), Receiver(base) { + assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, @@ -263,8 +555,9 @@ public: : Expr(ObjCPropertyRefExprClass, t, VK, OK, /*TypeDependent=*/false, false, st->isInstantiationDependentType(), st->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), Setter(0), + PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { + assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -273,8 +566,9 @@ public: : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, Base->isValueDependent(), Base->isInstantiationDependent(), Base->containsUnexpandedParameterPack()), - PropertyOrGetter(Getter, true), Setter(Setter), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -282,8 +576,9 @@ public: SourceLocation IdLoc, SourceLocation SuperLoc, QualType SuperTy) : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), - PropertyOrGetter(Getter, true), Setter(Setter), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, @@ -291,8 +586,9 @@ public: SourceLocation IdLoc, SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver) : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), - PropertyOrGetter(Getter, true), Setter(Setter), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } explicit ObjCPropertyRefExpr(EmptyShell Empty) @@ -313,7 +609,7 @@ public: ObjCMethodDecl *getImplicitPropertySetter() const { assert(isImplicitProperty()); - return Setter; + return SetterAndMethodRefFlags.getPointer(); } Selector getGetterSelector() const { @@ -328,6 +624,28 @@ public: return getExplicitProperty()->getSetterName(); } + /// \brief True if the property reference will result in a message to the + /// getter. + /// This applies to both implicit and explicit property references. + bool isMessagingGetter() const { + return SetterAndMethodRefFlags.getInt() & MethodRef_Getter; + } + + /// \brief True if the property reference will result in a message to the + /// setter. + /// This applies to both implicit and explicit property references. + bool isMessagingSetter() const { + return SetterAndMethodRefFlags.getInt() & MethodRef_Setter; + } + + void setIsMessagingGetter(bool val = true) { + setMethodRefFlag(MethodRef_Getter, val); + } + + void setIsMessagingSetter(bool val = true) { + setMethodRefFlag(MethodRef_Setter, val); + } + const Expr *getBase() const { return cast<Expr>(Receiver.get<Stmt*>()); } @@ -348,14 +666,15 @@ public: if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl()) ResultType = Getter->getResultType(); else - ResultType = getType(); + ResultType = PDecl->getType(); } else { const ObjCMethodDecl *Getter = getImplicitPropertyGetter(); - ResultType = Getter->getResultType(); // with reference! + if (Getter) + ResultType = Getter->getResultType(); // with reference! } return ResultType; } - + QualType getSetterArgType() const { QualType ArgType; if (isImplicitProperty()) { @@ -381,7 +700,7 @@ public: bool isSuperReceiver() const { return Receiver.is<const Type*>(); } bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange((isObjectReceiver() ? getBase()->getLocStart() : getReceiverLocation()), IdLoc); @@ -403,15 +722,19 @@ public: private: friend class ASTStmtReader; - void setExplicitProperty(ObjCPropertyDecl *D) { + friend class ASTStmtWriter; + void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { PropertyOrGetter.setPointer(D); PropertyOrGetter.setInt(false); - Setter = 0; + SetterAndMethodRefFlags.setPointer(0); + SetterAndMethodRefFlags.setInt(methRefFlags); } - void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) { + void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + unsigned methRefFlags) { PropertyOrGetter.setPointer(Getter); PropertyOrGetter.setInt(true); - this->Setter = Setter; + SetterAndMethodRefFlags.setPointer(Setter); + SetterAndMethodRefFlags.setInt(methRefFlags); } void setBase(Expr *Base) { Receiver = Base; } void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } @@ -419,7 +742,98 @@ private: void setLocation(SourceLocation L) { IdLoc = L; } void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; } + + void setMethodRefFlag(MethodRefFlags flag, bool val) { + unsigned f = SetterAndMethodRefFlags.getInt(); + if (val) + f |= flag; + else + f &= ~flag; + SetterAndMethodRefFlags.setInt(f); + } }; + +/// ObjCSubscriptRefExpr - used for array and dictionary subscripting. +/// array[4] = array[3]; dictionary[key] = dictionary[alt_key]; +/// +class ObjCSubscriptRefExpr : public Expr { + // Location of ']' in an indexing expression. + SourceLocation RBracket; + // array/dictionary base expression. + // for arrays, this is a numeric expression. For dictionaries, this is + // an objective-c object pointer expression. + enum { BASE, KEY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + + ObjCMethodDecl *GetAtIndexMethodDecl; + + // For immutable objects this is null. When ObjCSubscriptRefExpr is to read + // an indexed object this is null too. + ObjCMethodDecl *SetAtIndexMethodDecl; + +public: + + ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, + ExprValueKind VK, ExprObjectKind OK, + ObjCMethodDecl *getMethod, + ObjCMethodDecl *setMethod, SourceLocation RB) + : Expr(ObjCSubscriptRefExprClass, T, VK, OK, + base->isTypeDependent() || key->isTypeDependent(), + base->isValueDependent() || key->isValueDependent(), + base->isInstantiationDependent() || key->isInstantiationDependent(), + (base->containsUnexpandedParameterPack() || + key->containsUnexpandedParameterPack())), + RBracket(RB), + GetAtIndexMethodDecl(getMethod), + SetAtIndexMethodDecl(setMethod) + {SubExprs[BASE] = base; SubExprs[KEY] = key;} + + explicit ObjCSubscriptRefExpr(EmptyShell Empty) + : Expr(ObjCSubscriptRefExprClass, Empty) {} + + static ObjCSubscriptRefExpr *Create(ASTContext &C, + Expr *base, + Expr *key, QualType T, + ObjCMethodDecl *getMethod, + ObjCMethodDecl *setMethod, + SourceLocation RB); + + SourceLocation getRBracket() const { return RBracket; } + void setRBracket(SourceLocation RB) { RBracket = RB; } + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(SubExprs[BASE]->getLocStart(), RBracket); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSubscriptRefExprClass; + } + static bool classof(const ObjCSubscriptRefExpr *) { return true; } + + Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); } + void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; } + + Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); } + void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; } + + ObjCMethodDecl *getAtIndexMethodDecl() const { + return GetAtIndexMethodDecl; + } + + ObjCMethodDecl *setAtIndexMethodDecl() const { + return SetAtIndexMethodDecl; + } + + bool isArraySubscriptRefExpr() const { + return getKeyExpr()->getType()->isIntegralOrEnumerationType(); + } + + child_range children() { + return child_range(SubExprs, SubExprs+END_EXPR); + } +private: + friend class ASTStmtReader; +}; + /// \brief An expression that sends a message to the given Objective-C /// object or class. @@ -477,7 +891,11 @@ class ObjCMessageExpr : public Expr { /// \brief Whether this message send is a "delegate init call", /// i.e. a call of an init method on self from within an init method. unsigned IsDelegateInitCall : 1; - + + /// \brief Whether this message send was implicitly generated by + /// the implementation rather than explicitly written by the user. + unsigned IsImplicit : 1; + /// \brief Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. unsigned SelLocsKind : 2; @@ -492,7 +910,7 @@ class ObjCMessageExpr : public Expr { ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0), - HasMethod(0), IsDelegateInitCall(0) { + HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) { setNumArgs(NumArgs); } @@ -506,7 +924,8 @@ class ObjCMessageExpr : public Expr { SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, @@ -515,7 +934,8 @@ class ObjCMessageExpr : public Expr { SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); ObjCMessageExpr(QualType T, ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, @@ -524,7 +944,8 @@ class ObjCMessageExpr : public Expr { SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); void initArgsAndSelLocs(ArrayRef<Expr *> Args, ArrayRef<SourceLocation> SelLocs, @@ -625,7 +1046,8 @@ public: ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); /// \brief Create a class message send. /// @@ -660,7 +1082,8 @@ public: ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); /// \brief Create an instance message send. /// @@ -695,7 +1118,8 @@ public: ArrayRef<SourceLocation> SeLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc); + SourceLocation RBracLoc, + bool isImplicit); /// \brief Create an empty Objective-C message expression, to be /// filled in by subsequent calls. @@ -708,6 +1132,11 @@ public: unsigned NumArgs, unsigned NumStoredSelLocs); + /// \brief Indicates whether the message send was implicitly + /// generated by the implementation. If false, it was written explicitly + /// in the source code. + bool isImplicit() const { return IsImplicit; } + /// \brief Determine the kind of receiver that this message is being /// sent to. ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } @@ -877,7 +1306,11 @@ public: SourceLocation getLeftLoc() const { return LBracLoc; } SourceLocation getRightLoc() const { return RBracLoc; } - SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); } + SourceLocation getSelectorStartLoc() const { + if (isImplicit()) + return getLocStart(); + return getSelectorLoc(0); + } SourceLocation getSelectorLoc(unsigned Index) const { assert(Index < getNumSelectorLocs() && "Index out of range!"); if (hasStandardSelLocs()) @@ -892,6 +1325,8 @@ public: void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const; unsigned getNumSelectorLocs() const { + if (isImplicit()) + return 0; Selector Sel = getSelector(); if (Sel.isUnarySelector()) return 1; @@ -902,7 +1337,7 @@ public: LBracLoc = R.getBegin(); RBracLoc = R.getEnd(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LBracLoc, RBracLoc); } @@ -965,11 +1400,11 @@ public: SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBase()->getLocStart(), IsaMemberLoc); } - SourceLocation getExprLoc() const { return IsaMemberLoc; } + SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIsaExprClass; @@ -1038,8 +1473,12 @@ public: child_range children() { return child_range(&Operand, &Operand+1); } // Source locations are determined by the subexpression. - SourceRange getSourceRange() const { return Operand->getSourceRange(); } - SourceLocation getExprLoc() const { return getSubExpr()->getExprLoc(); } + SourceRange getSourceRange() const LLVM_READONLY { + return Operand->getSourceRange(); + } + SourceLocation getExprLoc() const LLVM_READONLY { + return getSubExpr()->getExprLoc(); + } static bool classof(const Stmt *s) { return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; @@ -1086,7 +1525,7 @@ public: /// \brief The location of the bridge keyword. SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LParenLoc, getSubExpr()->getLocEnd()); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h index 96d14b2..18a1432 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h @@ -15,6 +15,8 @@ #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #include "clang/AST/DeclBase.h" +#include "clang/AST/CharUnits.h" +#include "llvm/ADT/DenseMap.h" namespace clang { @@ -153,6 +155,12 @@ public: return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); } + /// \brief Get the decls that are contained in a file in the Offset/Length + /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// a range. + virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, + SmallVectorImpl<Decl *> &Decls) {} + /// \brief Gives the external AST source an opportunity to complete /// an incomplete type. virtual void CompleteType(TagDecl *Tag) {} @@ -190,6 +198,44 @@ public: /// The default implementation of this method is a no-op. virtual void PrintStats(); + + /// \brief Perform layout on the given record. + /// + /// This routine allows the external AST source to provide an specific + /// layout for a record, overriding the layout that would normally be + /// constructed. It is intended for clients who receive specific layout + /// details rather than source code (such as LLDB). The client is expected + /// to fill in the field offsets, base offsets, virtual base offsets, and + /// complete object size. + /// + /// \param Record The record whose layout is being requested. + /// + /// \param Size The final size of the record, in bits. + /// + /// \param Alignment The final alignment of the record, in bits. + /// + /// \param FieldOffsets The offset of each of the fields within the record, + /// expressed in bits. All of the fields must be provided with offsets. + /// + /// \param BaseOffsets The offset of each of the direct, non-virtual base + /// classes. If any bases are not given offsets, the bases will be laid + /// out according to the ABI. + /// + /// \param VirtualBaseOffsets The offset of each of the virtual base classes + /// (either direct or not). If any bases are not given offsets, the bases will be laid + /// out according to the ABI. + /// + /// \returns true if the record layout was provided, false otherwise. + virtual bool + layoutRecordType(const RecordDecl *Record, + uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) + { + return false; + } + //===--------------------------------------------------------------------===// // Queries for performance analysis. //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/include/clang/AST/LambdaMangleContext.h b/contrib/llvm/tools/clang/include/clang/AST/LambdaMangleContext.h new file mode 100644 index 0000000..3e2fbad --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/LambdaMangleContext.h @@ -0,0 +1,36 @@ +//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LambdaMangleContext interface, which keeps track of +// the Itanium C++ ABI mangling numbers for lambda expressions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H +#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H + +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +class CXXMethodDecl; +class FunctionProtoType; + +/// \brief Keeps track of the mangled names of lambda expressions within a +/// particular context. +class LambdaMangleContext { + llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers; + +public: + /// \brief Retrieve the mangling number of a new lambda expression with the + /// given call operator within this lambda context. + unsigned getManglingNumber(CXXMethodDecl *CallOperator); +}; + +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h index f58a83b..ca22ed6 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h @@ -58,12 +58,14 @@ public: private: StringRef String; - llvm::SmallString<256> Buffer; + SmallString<256> Buffer; }; /// MangleContext - Context for tracking state which persists across multiple /// calls to the C++ name mangler. class MangleContext { + virtual void anchor(); + ASTContext &Context; DiagnosticsEngine &Diags; diff --git a/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h new file mode 100644 index 0000000..40e9759 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h @@ -0,0 +1,152 @@ +//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_NSAPI_H +#define LLVM_CLANG_AST_NSAPI_H + +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/Optional.h" + +namespace clang { + class ASTContext; + class QualType; + +// \brief Provides info and caches identifiers/selectors for NSFoundation API. +class NSAPI { +public: + explicit NSAPI(ASTContext &Ctx); + + ASTContext &getASTContext() const { return Ctx; } + + enum NSClassIdKindKind { + ClassId_NSObject, + ClassId_NSString, + ClassId_NSArray, + ClassId_NSMutableArray, + ClassId_NSDictionary, + ClassId_NSMutableDictionary, + ClassId_NSNumber + }; + static const unsigned NumClassIds = 7; + + enum NSStringMethodKind { + NSStr_stringWithString, + NSStr_initWithString + }; + static const unsigned NumNSStringMethods = 2; + + IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; + + /// \brief The Objective-C NSString selectors. + Selector getNSStringSelector(NSStringMethodKind MK) const; + + /// \brief Enumerates the NSArray methods used to generate literals. + enum NSArrayMethodKind { + NSArr_array, + NSArr_arrayWithArray, + NSArr_arrayWithObject, + NSArr_arrayWithObjects, + NSArr_arrayWithObjectsCount, + NSArr_initWithArray, + NSArr_initWithObjects, + NSArr_objectAtIndex, + NSMutableArr_replaceObjectAtIndex + }; + static const unsigned NumNSArrayMethods = 9; + + /// \brief The Objective-C NSArray selectors. + Selector getNSArraySelector(NSArrayMethodKind MK) const; + + /// \brief Return NSArrayMethodKind if \arg Sel is such a selector. + llvm::Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); + + /// \brief Enumerates the NSDictionary methods used to generate literals. + enum NSDictionaryMethodKind { + NSDict_dictionary, + NSDict_dictionaryWithDictionary, + NSDict_dictionaryWithObjectForKey, + NSDict_dictionaryWithObjectsForKeys, + NSDict_dictionaryWithObjectsForKeysCount, + NSDict_dictionaryWithObjectsAndKeys, + NSDict_initWithDictionary, + NSDict_initWithObjectsAndKeys, + NSDict_objectForKey, + NSMutableDict_setObjectForKey + }; + static const unsigned NumNSDictionaryMethods = 10; + + /// \brief The Objective-C NSDictionary selectors. + Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; + + /// \brief Return NSDictionaryMethodKind if \arg Sel is such a selector. + llvm::Optional<NSDictionaryMethodKind> + getNSDictionaryMethodKind(Selector Sel); + + /// \brief Enumerates the NSNumber methods used to generate literals. + enum NSNumberLiteralMethodKind { + NSNumberWithChar, + NSNumberWithUnsignedChar, + NSNumberWithShort, + NSNumberWithUnsignedShort, + NSNumberWithInt, + NSNumberWithUnsignedInt, + NSNumberWithLong, + NSNumberWithUnsignedLong, + NSNumberWithLongLong, + NSNumberWithUnsignedLongLong, + NSNumberWithFloat, + NSNumberWithDouble, + NSNumberWithBool, + NSNumberWithInteger, + NSNumberWithUnsignedInteger + }; + static const unsigned NumNSNumberLiteralMethods = 15; + + /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. + /// \param Instance if true it will return the selector for the init* method + /// otherwise it will return the selector for the number* method. + Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, + bool Instance) const; + + bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, + Selector Sel) const { + return Sel == getNSNumberLiteralSelector(MK, false) || + Sel == getNSNumberLiteralSelector(MK, true); + } + + /// \brief Return NSNumberLiteralMethodKind if \arg Sel is such a selector. + llvm::Optional<NSNumberLiteralMethodKind> + getNSNumberLiteralMethodKind(Selector Sel) const; + + /// \brief Determine the appropriate NSNumber factory method kind for a + /// literal of the given type. + static llvm::Optional<NSNumberLiteralMethodKind> + getNSNumberFactoryMethodKind(QualType T); + +private: + ASTContext &Ctx; + + mutable IdentifierInfo *ClassIds[NumClassIds]; + + mutable Selector NSStringSelectors[NumNSStringMethods]; + + /// \brief The selectors for Objective-C NSArray methods. + mutable Selector NSArraySelectors[NumNSArrayMethods]; + + /// \brief The selectors for Objective-C NSDictionary methods. + mutable Selector NSDictionarySelectors[NumNSDictionaryMethods]; + + /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. + mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods]; + mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_NSAPI_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h index c81c06e..b5bd824 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h +++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h @@ -17,6 +17,7 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -36,8 +37,9 @@ class LangOptions; /// namespaces. For example, "foo::" in "foo::x" is a nested name /// specifier. Nested name specifiers are made up of a sequence of /// specifiers, each of which can be a namespace, type, identifier -/// (for dependent names), or the global specifier ('::', must be the -/// first specifier). +/// (for dependent names), decltype specifier, or the global specifier ('::'). +/// The last two specifiers can only appear at the start of a +/// nested-namespace-specifier. class NestedNameSpecifier : public llvm::FoldingSetNode { /// \brief Enumeration describing @@ -95,7 +97,8 @@ private: Specifier(Other.Specifier) { } - NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement + NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not + // implement /// \brief Either find or insert the given nested name specifier /// mockup in the given context. @@ -221,12 +224,12 @@ class NestedNameSpecifierLoc { public: /// \brief Construct an empty nested-name-specifier. NestedNameSpecifierLoc() : Qualifier(0), Data(0) { } - + /// \brief Construct a nested-name-specifier with source location information - /// from + /// from NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) : Qualifier(Qualifier), Data(Data) { } - + /// \brief Evalutes true when this nested-name-specifier location is /// non-empty. operator bool() const { return Qualifier; } @@ -239,14 +242,14 @@ public: /// \brief Retrieve the opaque pointer that refers to source-location data. void *getOpaqueData() const { return Data; } - + /// \brief Retrieve the source range covering the entirety of this /// nested-name-specifier. /// /// For example, if this instance refers to a nested-name-specifier /// \c ::std::vector<int>::, the returned source range would cover /// from the initial '::' to the last '::'. - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; /// \brief Retrieve the source range covering just the last part of /// this nested-name-specifier, not including the prefix. @@ -258,25 +261,25 @@ public: /// \brief Retrieve the location of the beginning of this /// nested-name-specifier. - SourceLocation getBeginLoc() const { + SourceLocation getBeginLoc() const { return getSourceRange().getBegin(); } /// \brief Retrieve the location of the end of this /// nested-name-specifier. - SourceLocation getEndLoc() const { + SourceLocation getEndLoc() const { return getSourceRange().getEnd(); } /// \brief Retrieve the location of the beginning of this /// component of the nested-name-specifier. - SourceLocation getLocalBeginLoc() const { + SourceLocation getLocalBeginLoc() const { return getLocalSourceRange().getBegin(); } - + /// \brief Retrieve the location of the end of this component of the /// nested-name-specifier. - SourceLocation getLocalEndLoc() const { + SourceLocation getLocalEndLoc() const { return getLocalSourceRange().getEnd(); } @@ -300,13 +303,13 @@ public: /// \brief Determines the data length for the entire /// nested-name-specifier. unsigned getDataLength() const { return getDataLength(Qualifier); } - - friend bool operator==(NestedNameSpecifierLoc X, + + friend bool operator==(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) { return X.Qualifier == Y.Qualifier && X.Data == Y.Data; } - friend bool operator!=(NestedNameSpecifierLoc X, + friend bool operator!=(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) { return !(X == Y); } @@ -316,39 +319,43 @@ public: /// with source-location information for all of the components of the /// nested-name-specifier. class NestedNameSpecifierLocBuilder { - /// \brief The current representation of the nested-name-specifier we're + /// \brief The current representation of the nested-name-specifier we're /// building. NestedNameSpecifier *Representation; - + /// \brief Buffer used to store source-location information for the /// nested-name-specifier. /// - /// Note that we explicitly manage the buffer (rather than using a + /// Note that we explicitly manage the buffer (rather than using a /// SmallVector) because \c Declarator expects it to be possible to memcpy() /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. char *Buffer; - + /// \brief The size of the buffer used to store source-location information /// for the nested-name-specifier. unsigned BufferSize; - - /// \brief The capacity of the buffer used to store source-location + + /// \brief The capacity of the buffer used to store source-location /// information for the nested-name-specifier. unsigned BufferCapacity; public: - NestedNameSpecifierLocBuilder(); - + NestedNameSpecifierLocBuilder() + : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { } + NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); - + NestedNameSpecifierLocBuilder & operator=(const NestedNameSpecifierLocBuilder &Other); - - ~NestedNameSpecifierLocBuilder(); - + + ~NestedNameSpecifierLocBuilder() { + if (BufferCapacity) + free(Buffer); + } + /// \brief Retrieve the representation of the nested-name-specifier. NestedNameSpecifier *getRepresentation() const { return Representation; } - + /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'type::'. /// @@ -362,8 +369,8 @@ public: /// \param ColonColonLoc The location of the trailing '::'. void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another + + /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'identifier::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -376,8 +383,8 @@ public: /// \param ColonColonLoc The location of the trailing '::'. void Extend(ASTContext &Context, IdentifierInfo *Identifier, SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another + + /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -390,8 +397,8 @@ public: /// \param ColonColonLoc The location of the trailing '::'. void Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - - /// \brief Extend the current nested-name-specifier by another + + /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace-alias::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -399,35 +406,35 @@ public: /// /// \param Alias The namespace alias. /// - /// \param AliasLoc The location of the namespace alias + /// \param AliasLoc The location of the namespace alias /// name. /// /// \param ColonColonLoc The location of the trailing '::'. void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, SourceLocation AliasLoc, SourceLocation ColonColonLoc); - + /// \brief Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); - + /// \brief Make a new nested-name-specifier from incomplete source-location /// information. /// /// This routine should be used very, very rarely, in cases where we /// need to synthesize a nested-name-specifier. Most code should instead use /// \c Adopt() with a proper \c NestedNameSpecifierLoc. - void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R); - - /// \brief Adopt an existing nested-name-specifier (with source-range + + /// \brief Adopt an existing nested-name-specifier (with source-range /// information). void Adopt(NestedNameSpecifierLoc Other); - + /// \brief Retrieve the source range covered by this nested-name-specifier. - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); } - + /// \brief Retrieve a nested-name-specifier with location information, /// copied into the given AST context. /// @@ -449,7 +456,7 @@ public: Representation = 0; BufferSize = 0; } - + /// \brief Retrieve the underlying buffer. /// /// \returns A pair containing a pointer to the buffer of source-location @@ -459,9 +466,9 @@ public: return std::make_pair(Buffer, BufferSize); } }; - -/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers -/// into a diagnostic with <<. + +/// Insertion operator for diagnostics. This allows sending +/// NestedNameSpecifiers into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, NestedNameSpecifier *NNS) { DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h index 469da99..258637d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h +++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h @@ -52,13 +52,6 @@ enum CastKind { /// conversion is always unqualified. CK_LValueToRValue, - /// CK_GetObjCProperty - A conversion which calls an Objective-C - /// property getter. The operand is an OK_ObjCProperty l-value; the - /// result will generally be an r-value, but could be an ordinary - /// gl-value if the property reference is to an implicit property - /// for a method that returns a reference type. - CK_GetObjCProperty, - /// CK_NoOp - A conversion which does not affect the type other than /// (possibly) adding qualifiers. /// int -> int @@ -124,6 +117,15 @@ enum CastKind { /// against the null member pointer. CK_MemberPointerToBoolean, + /// CK_ReinterpretMemberPointer - Reinterpret a member pointer as a + /// different kind of member pointer. C++ forbids this from + /// crossing between function and object types, but otherwise does + /// not restrict it. However, the only operation that is permitted + /// on a "punned" member pointer is casting it back to the original + /// type, which is required to be a lossless operation (although + /// many ABIs do not guarantee this on all possible intermediate types). + CK_ReinterpretMemberPointer, + /// CK_UserDefinedConversion - Conversion using a user defined type /// conversion function. /// struct A { operator int(); }; int i = int(A()); @@ -274,7 +276,19 @@ enum CastKind { /// in ARC cause blocks to be copied; this is for cases where that /// would not otherwise be guaranteed, such as when casting to a /// non-block pointer type. - CK_ARCExtendBlockObject + CK_ARCExtendBlockObject, + + /// \brief Converts from _Atomic(T) to T. + CK_AtomicToNonAtomic, + /// \brief Converts from T to _Atomic(T). + CK_NonAtomicToAtomic, + + /// \brief Causes a block literal to by copied to the heap and then + /// autoreleased. + /// + /// This particular cast kind is used for the conversion from a C++11 + /// lambda expression to a block pointer. + CK_CopyAndAutoreleaseBlockObject }; #define CK_Invalid ((CastKind) -1) diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h index 2bdd8d3..2e34dc8 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h @@ -36,7 +36,7 @@ struct PrintingPolicy { PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), - SuppressInitializers(false), + SuppressUnwrittenScope(false), SuppressInitializers(false), Dump(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), Bool(LO.Bool) { } @@ -86,6 +86,10 @@ struct PrintingPolicy { /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; + /// \brief Suppress printing parts of scope specifiers that don't need + /// to be written, e.g., for inline or anonymous namespaces. + bool SuppressUnwrittenScope : 1; + /// \brief Suppress printing of variable initializers. /// /// This flag is used when printing the loop variable in a for-range diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h index b0186ce..ec07267 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h @@ -62,8 +62,11 @@ class ASTRecordLayout { /// (either a base or a member). Will be zero if the class doesn't contain /// any empty subobjects. CharUnits SizeOfLargestEmptySubobject; - - /// VBPtrOffset - Virtual base table offset. + + /// VFPtrOffset - Virtual function table offset (Microsoft-only). + CharUnits VFPtrOffset; + + /// VBPtrOffset - Virtual base table offset (Microsoft-only). CharUnits VBPtrOffset; /// PrimaryBase - The primary base info for this record. @@ -92,7 +95,8 @@ class ASTRecordLayout { // Constructor for C++ records. typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; ASTRecordLayout(const ASTContext &Ctx, - CharUnits size, CharUnits alignment, CharUnits vbptroffset, + CharUnits size, CharUnits alignment, + CharUnits vfptroffset, CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, CharUnits nonvirtualalign, @@ -204,7 +208,17 @@ public: return CXXInfo->SizeOfLargestEmptySubobject; } + /// getVFPtrOffset - Get the offset for virtual function table pointer. + /// This is only meaningful with the Microsoft ABI. + CharUnits getVFPtrOffset() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->VFPtrOffset; + } + + /// getVBPtrOffset - Get the offset for virtual base table pointer. + /// This is only meaningful with the Microsoft ABI. CharUnits getVBPtrOffset() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->VBPtrOffset; } }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h index 0ec09c9..a4ad525 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h @@ -147,7 +147,13 @@ public: /// \brief Return whether this visitor should recurse into the types of /// TypeLocs. bool shouldWalkTypesOfTypeLocs() const { return true; } - + + /// \brief Return whether \param S should be traversed using data recursion + /// to avoid a stack overflow with extreme cases. + bool shouldUseDataRecursionFor(Stmt *S) const { + return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) || isa<CaseStmt>(S); + } + /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// @@ -181,12 +187,17 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - /// \brief Recursively visit a C++ nested-name-specifier with location + /// \brief Recursively visit a C++ nested-name-specifier with location /// information. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + /// \brief Recursively visit a name with its location information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); + /// \brief Recursively visit a template name and dispatch to the /// appropriate method. /// @@ -223,6 +234,11 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseConstructorInitializer(CXXCtorInitializer *Init); + /// \brief Recursively visit a lambda capture. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseLambdaCapture(LambdaExpr::Capture C); + // ---- Methods on Stmts ---- // Declare Traverse*() for all concrete Stmt classes. @@ -387,8 +403,102 @@ private: bool TraverseDeclContextHelper(DeclContext *DC); bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); + + bool Walk(Stmt *S); + + struct EnqueueJob { + Stmt *S; + Stmt::child_iterator StmtIt; + + EnqueueJob(Stmt *S) : S(S), StmtIt() { + if (Expr *E = dyn_cast_or_null<Expr>(S)) + S = E->IgnoreParens(); + } + }; + bool dataTraverse(Stmt *S); }; +template<typename Derived> +bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { + + SmallVector<EnqueueJob, 16> Queue; + Queue.push_back(S); + + while (!Queue.empty()) { + EnqueueJob &job = Queue.back(); + Stmt *CurrS = job.S; + if (!CurrS) { + Queue.pop_back(); + continue; + } + + if (getDerived().shouldUseDataRecursionFor(CurrS)) { + if (job.StmtIt == Stmt::child_iterator()) { + if (!Walk(CurrS)) return false; + job.StmtIt = CurrS->child_begin(); + } else { + ++job.StmtIt; + } + + if (job.StmtIt != CurrS->child_end()) + Queue.push_back(*job.StmtIt); + else + Queue.pop_back(); + continue; + } + + Queue.pop_back(); + TRY_TO(TraverseStmt(CurrS)); + } + + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) { + +#define DISPATCH_WALK(NAME, CLASS, VAR) \ + return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); + + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { +#define OPERATOR(NAME) \ + case BO_##NAME: DISPATCH_WALK(Bin##NAME, BinaryOperator, S); + + BINOP_LIST() +#undef OPERATOR + +#define OPERATOR(NAME) \ + case BO_##NAME##Assign: \ + DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S); + + CAO_LIST() +#undef OPERATOR + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { +#define OPERATOR(NAME) \ + case UO_##NAME: DISPATCH_WALK(Unary##NAME, UnaryOperator, S); + + UNARYOP_LIST() +#undef OPERATOR + } + } + + // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: DISPATCH_WALK(CLASS, CLASS, S); +#include "clang/AST/StmtNodes.inc" + } + +#undef DISPATCH_WALK + + return true; +} + #define DISPATCH(NAME, CLASS, VAR) \ return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)) @@ -397,6 +507,9 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (!S) return true; + if (getDerived().shouldUseDataRecursionFor(S)) + return dataTraverse(S); + // If we have a binary expr, dispatch to the subcode of the binop. A smart // optimizer (e.g. LLVM) will fold this comparison into the switch stmt // below. @@ -525,23 +638,48 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( NestedNameSpecifierLoc NNS) { if (!NNS) return true; - + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); - + switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return true; - + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); break; } - + + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( + DeclarationNameInfo NameInfo) { + switch (NameInfo.getName().getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) + TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); + + break; + + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + break; + } + return true; } @@ -600,7 +738,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( // FIXME: how can TSI ever be NULL? if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else + else return getDerived().TraverseType(Arg.getAsType()); } @@ -637,12 +775,18 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( CXXCtorInitializer *Init) { - // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()? + if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); + if (Init->isWritten()) TRY_TO(TraverseStmt(Init->getInit())); return true; } +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr::Capture C){ + return true; +} // ----------------- Type traversal ----------------- @@ -822,8 +966,8 @@ DEF_TRAVERSE_TYPE(AtomicType, { // ----------------- TypeLoc traversal ----------------- // This macro makes available a variable TL, the passed-in TypeLoc. -// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, -// in addition to WalkUpFrom* for the TypeLoc itself, such that existing +// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, +// in addition to WalkUpFrom* for the TypeLoc itself, such that existing // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods // continue to work. #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ @@ -1022,7 +1166,7 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { if (TL.getQualifierLoc()) { TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); } - + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); } @@ -1099,6 +1243,8 @@ DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) +DEF_TRAVERSE_DECL(ImportDecl, { }) + DEF_TRAVERSE_DECL(FriendDecl, { // Friend is either decl or a type. if (D->getFriendType()) @@ -1128,14 +1274,6 @@ DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) -DEF_TRAVERSE_DECL(ObjCClassDecl, { - // FIXME: implement this - }) - -DEF_TRAVERSE_DECL(ObjCForwardProtocolDecl, { - // FIXME: implement this - }) - DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, { // FIXME: implement this }) @@ -1164,8 +1302,8 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, { DEF_TRAVERSE_DECL(LabelDecl, { // There is no code in a LabelDecl. }) - - + + DEF_TRAVERSE_DECL(NamespaceDecl, { // Code in an unnamed namespace shows up automatically in // decls_begin()/decls_end(). Thus we don't need to recurse on @@ -1216,6 +1354,7 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, { DEF_TRAVERSE_DECL(UsingDecl, { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); }) DEF_TRAVERSE_DECL(UsingDirectiveDecl, { @@ -1312,7 +1451,8 @@ template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( FunctionTemplateDecl* D) { FunctionTemplateDecl::spec_iterator end = D->spec_end(); - for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; + ++it) { FunctionDecl* FD = *it; switch (FD->getTemplateSpecializationKind()) { case TSK_ImplicitInstantiation: @@ -1329,8 +1469,6 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( case TSK_Undeclared: // Declaration of the template definition. case TSK_ExplicitSpecialization: break; - default: - llvm_unreachable("Unknown specialization kind."); } } @@ -1511,6 +1649,7 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { // Like UnresolvedUsingTypenameDecl, but without the 'typename': // template <class T> Class A : public Base<T> { using Base<T>::foo; }; TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); }) DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) @@ -1529,6 +1668,8 @@ DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) TRY_TO(TraverseStmt(D->getBitWidth())); + else if (D->hasInClassInitializer()) + TRY_TO(TraverseStmt(D->getInClassInitializer())); }) DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { @@ -1548,6 +1689,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); // If we're an explicit template specialization, iterate over the // template args that were explicitly specified. If we were doing @@ -1624,7 +1766,9 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { TRY_TO(TraverseDeclaratorHelper(D)); - TRY_TO(TraverseStmt(D->getInit())); + // Default params are taken care of when we traverse the ParmVarDecl. + if (!isa<ParmVarDecl>(D)) + TRY_TO(TraverseStmt(D->getInit())); return true; } @@ -1735,6 +1879,10 @@ DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { }) DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) +DEF_TRAVERSE_STMT(MSDependentExistsStmt, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); +}) DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { }) @@ -1742,6 +1890,7 @@ DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1750,12 +1899,14 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { DEF_TRAVERSE_STMT(DeclRefExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); }) DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getExplicitTemplateArgs().getTemplateArgs(), @@ -1765,6 +1916,7 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { DEF_TRAVERSE_STMT(MemberExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); }) @@ -1831,6 +1983,23 @@ TraverseGenericSelectionExpr(GenericSelectionExpr *S) { return true; } +// PseudoObjectExpr is a special case because of the wierdness with +// syntactic expressions and opaque values. +template<typename Derived> +bool RecursiveASTVisitor<Derived>:: +TraversePseudoObjectExpr(PseudoObjectExpr *S) { + TRY_TO(WalkUpFromPseudoObjectExpr(S)); + TRY_TO(TraverseStmt(S->getSyntacticForm())); + for (PseudoObjectExpr::semantics_iterator + i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) { + Expr *sub = *i; + if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) + sub = OVE->getSourceExpr(); + TRY_TO(TraverseStmt(sub)); + } + return true; +} + DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in // (i.e. non-class) type. @@ -1880,6 +2049,11 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(TypeTraitExpr, { + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); +}) + DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); }) @@ -1898,6 +2072,37 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) +// Walk only the visible parts of lambda expressions. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), + CEnd = S->explicit_capture_end(); + C != CEnd; ++C) { + TRY_TO(TraverseLambdaCapture(*C)); + } + + if (S->hasExplicitParameters() || S->hasExplicitResultType()) { + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else if (isa<FunctionProtoTypeLoc>(TL)) { + FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL); + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getArg(I))); + } + } else { + TRY_TO(TraverseTypeLoc(Proto.getResultLoc())); + } + } + } + + TRY_TO(TraverseStmt(S->getBody())); + return true; +} + DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { // This is called for code like 'T()', where T is a template argument. TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); @@ -1913,7 +2118,6 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, { }) DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) -DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) DEF_TRAVERSE_STMT(BlockExpr, { TRY_TO(TraverseDecl(S->getBlockDecl())); return true; // no child statements to loop through. @@ -1926,7 +2130,7 @@ DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) -DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { +DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); @@ -1935,15 +2139,18 @@ DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) DEF_TRAVERSE_STMT(CXXThisExpr, { }) DEF_TRAVERSE_STMT(CXXThrowExpr, { }) +DEF_TRAVERSE_STMT(UserDefinedLiteral, { }) DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) DEF_TRAVERSE_STMT(GNUNullExpr, { }) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) +DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) +DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { }) @@ -1958,15 +2165,15 @@ DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); } }) - + DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); } }) @@ -2001,6 +2208,9 @@ DEF_TRAVERSE_STMT(FloatingLiteral, { }) DEF_TRAVERSE_STMT(ImaginaryLiteral, { }) DEF_TRAVERSE_STMT(StringLiteral, { }) DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) +DEF_TRAVERSE_STMT(ObjCNumericLiteral, { }) +DEF_TRAVERSE_STMT(ObjCArrayLiteral, { }) +DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) // Traverse OpenCL: AsType, Convert. DEF_TRAVERSE_STMT(AsTypeExpr, { }) diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h index e87ca78..88abadb 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h @@ -64,22 +64,22 @@ public: /// \brief Return the previous declaration of this declaration or NULL if this /// is the first declaration. - decl_type *getPreviousDeclaration() { + decl_type *getPreviousDecl() { if (RedeclLink.NextIsPrevious()) return RedeclLink.getNext(); return 0; } - const decl_type *getPreviousDeclaration() const { + const decl_type *getPreviousDecl() const { return const_cast<decl_type *>( - static_cast<const decl_type*>(this))->getPreviousDeclaration(); + static_cast<const decl_type*>(this))->getPreviousDecl(); } /// \brief Return the first declaration of this declaration or itself if this /// is the only declaration. decl_type *getFirstDeclaration() { decl_type *D = static_cast<decl_type*>(this); - while (D->getPreviousDeclaration()) - D = D->getPreviousDeclaration(); + while (D->getPreviousDecl()) + D = D->getPreviousDecl(); return D; } @@ -87,8 +87,8 @@ public: /// is the only declaration. const decl_type *getFirstDeclaration() const { const decl_type *D = static_cast<const decl_type*>(this); - while (D->getPreviousDeclaration()) - D = D->getPreviousDeclaration(); + while (D->getPreviousDecl()) + D = D->getPreviousDecl(); return D; } @@ -98,12 +98,12 @@ public: } /// \brief Returns the most recent (re)declaration of this declaration. - decl_type *getMostRecentDeclaration() { + decl_type *getMostRecentDecl() { return getFirstDeclaration()->RedeclLink.getNext(); } /// \brief Returns the most recent (re)declaration of this declaration. - const decl_type *getMostRecentDeclaration() const { + const decl_type *getMostRecentDecl() const { return getFirstDeclaration()->RedeclLink.getNext(); } @@ -116,6 +116,7 @@ public: /// Current - The current declaration. decl_type *Current; decl_type *Starter; + bool PassedFirst; public: typedef decl_type* value_type; @@ -125,13 +126,24 @@ public: typedef std::ptrdiff_t difference_type; redecl_iterator() : Current(0) { } - explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { } + explicit redecl_iterator(decl_type *C) + : Current(C), Starter(C), PassedFirst(false) { } reference operator*() const { return Current; } pointer operator->() const { return Current; } redecl_iterator& operator++() { assert(Current && "Advancing while iterator has reached end"); + // Sanity check to avoid infinite loop on invalid redecl chain. + if (Current->isFirstDeclaration()) { + if (PassedFirst) { + assert(0 && "Passed first decl twice, invalid redecl chain!"); + Current = 0; + return *this; + } + PassedFirst = true; + } + // Get either previous decl or latest decl. decl_type *Next = Current->RedeclLink.getNext(); Current = (Next != Starter ? Next : 0); diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h index 2a6fd6b..84bdfb8 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h @@ -20,8 +20,9 @@ #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/ASTContext.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" #include <string> namespace llvm { @@ -39,11 +40,11 @@ namespace clang { class StringLiteral; class SwitchStmt; - //===----------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// // ExprIterator - Iterators for iterating over Stmt* arrays that contain // only Expr*. This is needed because AST nodes use Stmt* arrays to store // references to children (to be compatible with StmtIterator). - //===----------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// class Stmt; class Expr; @@ -141,11 +142,14 @@ protected: friend class CallExpr; // ctor friend class OffsetOfExpr; // ctor friend class ObjCMessageExpr; // ctor + friend class ObjCArrayLiteral; // ctor + friend class ObjCDictionaryLiteral; // ctor friend class ShuffleVectorExpr; // ctor friend class ParenListExpr; // ctor friend class CXXUnresolvedConstructExpr; // ctor friend class CXXDependentScopeMemberExpr; // ctor friend class OverloadExpr; // ctor + friend class PseudoObjectExpr; // ctor friend class AtomicExpr; // ctor unsigned : NumStmtBits; @@ -158,15 +162,39 @@ protected: }; enum { NumExprBits = 16 }; + class CharacterLiteralBitfields { + friend class CharacterLiteral; + unsigned : NumExprBits; + + unsigned Kind : 2; + }; + + class FloatingLiteralBitfields { + friend class FloatingLiteral; + unsigned : NumExprBits; + + unsigned IsIEEE : 1; // Distinguishes between PPC128 and IEEE128. + unsigned IsExact : 1; + }; + + class UnaryExprOrTypeTraitExprBitfields { + friend class UnaryExprOrTypeTraitExpr; + unsigned : NumExprBits; + + unsigned Kind : 2; + unsigned IsType : 1; // true if operand is a type, false if an expression. + }; + class DeclRefExprBitfields { friend class DeclRefExpr; friend class ASTStmtReader; // deserialization unsigned : NumExprBits; unsigned HasQualifier : 1; - unsigned HasExplicitTemplateArgs : 1; + unsigned HasTemplateKWAndArgsInfo : 1; unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; + unsigned RefersToEnclosingLocal : 1; }; class CastExprBitfields { @@ -184,6 +212,27 @@ protected: unsigned NumPreArgs : 1; }; + class ExprWithCleanupsBitfields { + friend class ExprWithCleanups; + friend class ASTStmtReader; // deserialization + + unsigned : NumExprBits; + + unsigned NumObjects : 32 - NumExprBits; + }; + + class PseudoObjectExprBitfields { + friend class PseudoObjectExpr; + friend class ASTStmtReader; // deserialization + + unsigned : NumExprBits; + + // These don't need to be particularly wide, because they're + // strictly limited by the forms of expressions we permit. + unsigned NumSubExprs : 8; + unsigned ResultIndex : 32 - 8 - NumExprBits; + }; + class ObjCIndirectCopyRestoreExprBitfields { friend class ObjCIndirectCopyRestoreExpr; unsigned : NumExprBits; @@ -191,6 +240,38 @@ protected: unsigned ShouldCopy : 1; }; + class InitListExprBitfields { + friend class InitListExpr; + + unsigned : NumExprBits; + + /// Whether this initializer list originally had a GNU array-range + /// designator in it. This is a temporary marker used by CodeGen. + unsigned HadArrayRangeDesignator : 1; + + /// Whether this initializer list initializes a std::initializer_list + /// object. + unsigned InitializesStdInitializerList : 1; + }; + + class TypeTraitExprBitfields { + friend class TypeTraitExpr; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + unsigned : NumExprBits; + + /// \brief The kind of type trait, which is a value of a TypeTrait enumerator. + unsigned Kind : 8; + + /// \brief If this expression is not value-dependent, this indicates whether + /// the trait evaluated true or false. + unsigned Value : 1; + + /// \brief The number of arguments to this type trait. + unsigned NumArgs : 32 - 8 - 1 - NumExprBits; + }; + union { // FIXME: this is wasteful on 64-bit platforms. void *Aligner; @@ -198,13 +279,21 @@ protected: StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; ExprBitfields ExprBits; + CharacterLiteralBitfields CharacterLiteralBits; + FloatingLiteralBitfields FloatingLiteralBits; + UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; DeclRefExprBitfields DeclRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; + ExprWithCleanupsBitfields ExprWithCleanupsBits; + PseudoObjectExprBitfields PseudoObjectExprBits; ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; + InitListExprBitfields InitListExprBits; + TypeTraitExprBitfields TypeTraitExprBits; }; friend class ASTStmtReader; + friend class ASTStmtWriter; public: // Only allow allocation of Stmts using the allocator in ASTContext @@ -234,20 +323,24 @@ public: /// de-serialization). struct EmptyShell { }; +private: + /// \brief Whether statistic collection is enabled. + static bool StatisticsEnabled; + protected: /// \brief Construct an empty statement. explicit Stmt(StmtClass SC, EmptyShell) { StmtBits.sClass = SC; - if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + if (StatisticsEnabled) Stmt::addStmtClass(SC); } public: Stmt(StmtClass SC) { StmtBits.sClass = SC; - if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + if (StatisticsEnabled) Stmt::addStmtClass(SC); } - StmtClass getStmtClass() const { + StmtClass getStmtClass() const { return static_cast<StmtClass>(StmtBits.sClass); } const char *getStmtClassName() const; @@ -255,21 +348,20 @@ public: /// SourceLocation tokens are not useful in isolation - they are low level /// value objects created/interpreted by SourceManager. We assume AST /// clients will have a pointer to the respective SourceManager. - SourceRange getSourceRange() const; - - SourceLocation getLocStart() const { return getSourceRange().getBegin(); } - SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; // global temp stats (until we have a per-module visitor) static void addStmtClass(const StmtClass s); - static bool CollectingStats(bool Enable = false); + static void EnableStatistics(); static void PrintStats(); /// dump - This does a local dump of the specified AST fragment. It dumps the /// specified node and a few nodes underneath it, but not the whole subtree. /// This is useful in a debugger. - void dump() const; - void dump(SourceManager &SM) const; + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; void dump(raw_ostream &OS, SourceManager &SM) const; /// dumpAll - This does a dump of the specified AST fragment and all subtrees. @@ -384,7 +476,7 @@ public: SourceLocation getEndLoc() const { return EndLoc; } void setEndLoc(SourceLocation L) { EndLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(StartLoc, EndLoc); } @@ -433,7 +525,7 @@ public: bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; } - SourceRange getSourceRange() const { return SourceRange(SemiLoc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(SemiLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == NullStmtClass; @@ -483,7 +575,7 @@ public: body_iterator body_begin() { return Body; } body_iterator body_end() { return Body + size(); } Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; } - + void setLastStmt(Stmt *S) { assert(!body_empty() && "setLastStmt"); Body[size()-1] = S; @@ -513,7 +605,7 @@ public: return const_reverse_body_iterator(body_begin()); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LBracLoc, RBracLoc); } @@ -531,7 +623,7 @@ public: child_range children() { return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts); } - + const_child_range children() const { return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts); } @@ -558,7 +650,7 @@ public: return const_cast<SwitchCase*>(this)->getSubStmt(); } - SourceRange getSourceRange() const { return SourceRange(); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass || @@ -613,7 +705,7 @@ public: void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) @@ -653,7 +745,7 @@ public: SourceLocation getColonLoc() const { return ColonLoc; } void setColonLoc(SourceLocation L) { ColonLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(DefaultLoc, SubStmt->getLocEnd()); } static bool classof(const Stmt *T) { @@ -665,7 +757,7 @@ public: child_range children() { return child_range(&SubStmt, &SubStmt+1); } }; - + /// LabelStmt - Represents a label, which has a substatement. For example: /// foo: return; /// @@ -690,7 +782,7 @@ public: void setIdentLoc(SourceLocation L) { IdentLoc = L; } void setSubStmt(Stmt *SS) { SubStmt = SS; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(IdentLoc, SubStmt->getLocEnd()); } child_range children() { return child_range(&SubStmt, &SubStmt+1); } @@ -710,11 +802,11 @@ class IfStmt : public Stmt { SourceLocation IfLoc; SourceLocation ElseLoc; - + public: - IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0); - + /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } @@ -728,13 +820,13 @@ public: /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); - + /// If this IfStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. const DeclStmt *getConditionVariableDeclStmt() const { return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); } - + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -751,7 +843,7 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { if (SubExprs[ELSE]) return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); else @@ -801,7 +893,7 @@ public: /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); - + /// If this SwitchStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. const DeclStmt *getConditionVariableDeclStmt() const { @@ -832,7 +924,8 @@ public: SwitchLoc = SL; } void addSwitchCase(SwitchCase *SC) { - assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); + assert(!SC->getNextSwitchCase() + && "case/default already added to a switch"); SC->setNextSwitchCase(FirstCase); FirstCase = SC; } @@ -849,7 +942,7 @@ public: return (bool) AllEnumCasesCovered; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); } // Iterators @@ -871,7 +964,7 @@ class WhileStmt : public Stmt { Stmt* SubExprs[END_EXPR]; SourceLocation WhileLoc; public: - WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, + WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL); /// \brief Build an empty while statement. @@ -904,7 +997,7 @@ public: SourceLocation getWhileLoc() const { return WhileLoc; } void setWhileLoc(SourceLocation L) { WhileLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -953,7 +1046,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(DoLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -979,14 +1072,14 @@ class ForStmt : public Stmt { SourceLocation LParenLoc, RParenLoc; public: - ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, + ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP); /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } Stmt *getInit() { return SubExprs[INIT]; } - + /// \brief Retrieve the variable declared in this "for" statement, if any. /// /// In the following example, "y" is the condition variable. @@ -997,7 +1090,7 @@ public: /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); - + /// If this ForStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. const DeclStmt *getConditionVariableDeclStmt() const { @@ -1025,7 +1118,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -1060,7 +1153,7 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(GotoLoc, LabelLoc); } static bool classof(const Stmt *T) { @@ -1104,7 +1197,7 @@ public: return const_cast<IndirectGotoStmt*>(this)->getConstantTarget(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(GotoLoc, Target->getLocEnd()); } @@ -1131,7 +1224,7 @@ public: SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(ContinueLoc); } @@ -1157,7 +1250,7 @@ public: SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } - SourceRange getSourceRange() const { return SourceRange(BreakLoc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BreakLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == BreakStmtClass; @@ -1182,7 +1275,7 @@ class ReturnStmt : public Stmt { Stmt *RetExpr; SourceLocation RetLoc; const VarDecl *NRVOCandidate; - + public: ReturnStmt(SourceLocation RL) : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { } @@ -1208,8 +1301,8 @@ public: /// also marked as an NRVO object. const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } - - SourceRange getSourceRange() const; + + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == ReturnStmtClass; @@ -1242,16 +1335,16 @@ class AsmStmt : public Stmt { StringLiteral **Constraints; Stmt **Exprs; StringLiteral **Clobbers; - + public: - AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, + AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, bool msasm, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc); /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty), + explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty), Names(0), Constraints(0), Exprs(0), Clobbers(0) { } SourceLocation getAsmLoc() const { return AsmLoc; } @@ -1333,7 +1426,7 @@ public: StringRef getOutputName(unsigned i) const { if (IdentifierInfo *II = getOutputIdentifier(i)) return II->getName(); - + return StringRef(); } @@ -1394,7 +1487,7 @@ public: Expr *getInputExpr(unsigned i); void setInputExpr(unsigned i, Expr *E); - + const Expr *getInputExpr(unsigned i) const { return const_cast<AsmStmt*>(this)->getInputExpr(i); } @@ -1404,7 +1497,7 @@ public: StringLiteral **Constraints, Stmt **Exprs, unsigned NumOutputs, - unsigned NumInputs, + unsigned NumInputs, StringLiteral **Clobbers, unsigned NumClobbers); @@ -1419,7 +1512,7 @@ public: StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AsmLoc, RParenLoc); } @@ -1490,15 +1583,20 @@ public: SourceLocation ExceptLoc, Expr *FilterExpr, Stmt *Block); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getExceptLoc(), getEndLoc()); } SourceLocation getExceptLoc() const { return Loc; } SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } - Expr *getFilterExpr() const { return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); } - CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Children[BLOCK]); } + Expr *getFilterExpr() const { + return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); + } + + CompoundStmt *getBlock() const { + return llvm::cast<CompoundStmt>(Children[BLOCK]); + } child_range children() { return child_range(Children,Children+2); @@ -1528,7 +1626,7 @@ public: SourceLocation FinallyLoc, Stmt *Block); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getFinallyLoc(), getEndLoc()); } @@ -1572,7 +1670,7 @@ public: Stmt *TryBlock, Stmt *Handler); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getTryLoc(), getEndLoc()); } @@ -1580,7 +1678,11 @@ public: SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } bool getIsCXXTry() const { return IsCXXTry; } - CompoundStmt* getTryBlock() const { return llvm::cast<CompoundStmt>(Children[TRY]); } + + CompoundStmt* getTryBlock() const { + return llvm::cast<CompoundStmt>(Children[TRY]); + } + Stmt *getHandler() const { return Children[HANDLER]; } /// Returns 0 if not defined @@ -1596,7 +1698,6 @@ public: } static bool classof(SEHTryStmt *) { return true; } - }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h index 42dcf2b..a948722 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_STMTCXX_H #include "clang/AST/Stmt.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -37,7 +38,7 @@ public: CXXCatchStmt(EmptyShell Empty) : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } @@ -83,7 +84,7 @@ public: static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, unsigned numHandlers); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getTryLoc(), getEndLoc()); } @@ -148,7 +149,9 @@ public: DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } - DeclStmt *getBeginEndStmt() { return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); } + DeclStmt *getBeginEndStmt() { + return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); + } Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } @@ -187,7 +190,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -201,6 +204,91 @@ public: } }; +/// \brief Representation of a Microsoft __if_exists or __if_not_exists +/// statement with a dependent name. +/// +/// The __if_exists statement can be used to include a sequence of statements +/// in the program only when a particular dependent name does not exist. For +/// example: +/// +/// \code +/// template<typename T> +/// void call_foo(T &t) { +/// __if_exists (T::foo) { +/// t.foo(); // okay: only called when T::foo exists. +/// } +/// } +/// \endcode +/// +/// Similarly, the __if_not_exists statement can be used to include the +/// statements when a particular name does not exist. +/// +/// Note that this statement only captures __if_exists and __if_not_exists +/// statements whose name is dependent. All non-dependent cases are handled +/// directly in the parser, so that they don't introduce a new scope. Clang +/// introduces scopes in the dependent case to keep names inside the compound +/// statement from leaking out into the surround statements, which would +/// compromise the template instantiation model. This behavior differs from +/// Visual C++ (which never introduces a scope), but is a fairly reasonable +/// approximation of the VC++ behavior. +class MSDependentExistsStmt : public Stmt { + SourceLocation KeywordLoc; + bool IsIfExists; + NestedNameSpecifierLoc QualifierLoc; + DeclarationNameInfo NameInfo; + Stmt *SubStmt; + + friend class ASTReader; + friend class ASTStmtReader; + +public: + MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + CompoundStmt *SubStmt) + : Stmt(MSDependentExistsStmtClass), + KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), + QualifierLoc(QualifierLoc), NameInfo(NameInfo), + SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } + + /// \brief Retrieve the location of the __if_exists or __if_not_exists + /// keyword. + SourceLocation getKeywordLoc() const { return KeywordLoc; } + + /// \brief Determine whether this is an __if_exists statement. + bool isIfExists() const { return IsIfExists; } + + /// \brief Determine whether this is an __if_exists statement. + bool isIfNotExists() const { return !IsIfExists; } + + /// \brief Retrieve the nested-name-specifier that qualifies this name, if + /// any. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the name of the entity we're testing for, along with + /// location information + DeclarationNameInfo getNameInfo() const { return NameInfo; } + + /// \brief Retrieve the compound statement that will be included in the + /// program only if the existence of the symbol matches the initial keyword. + CompoundStmt *getSubStmt() const { + return reinterpret_cast<CompoundStmt *>(SubStmt); + } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(KeywordLoc, SubStmt->getLocEnd()); + } + + child_range children() { + return child_range(&SubStmt, &SubStmt+1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSDependentExistsStmtClass; + } + + static bool classof(MSDependentExistsStmt *) { return true; } +}; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h index 05b50db..b933ed0 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h @@ -90,14 +90,12 @@ public: StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {} DERIVED& operator++() { - if (inDecl() || inDeclGroup()) { - if (getVAPtr()) NextVA(); - else NextDecl(); - } - else if (inSizeOfTypeVA()) + if (inStmt()) + ++stmt; + else if (getVAPtr()) NextVA(); else - ++stmt; + NextDecl(); return static_cast<DERIVED&>(*this); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h index d996fc5..a321041 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_STMTOBJC_H #include "clang/AST/Stmt.h" +#include "llvm/Support/Compiler.h" namespace clang { @@ -55,7 +56,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); } static bool classof(const Stmt *T) { @@ -103,7 +104,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtCatchLoc, Body->getLocEnd()); } @@ -133,7 +134,7 @@ public: Stmt *getFinallyBody() { return AtFinallyStmt; } void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); } @@ -240,7 +241,7 @@ public: getStmts()[1 + NumCatchStmts] = S; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; @@ -294,7 +295,7 @@ public: } void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); } @@ -327,7 +328,7 @@ public: SourceLocation getThrowLoc() { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { if (Throw) return SourceRange(AtThrowLoc, Throw->getLocEnd()); else @@ -360,7 +361,7 @@ public: Stmt *getSubStmt() { return SubStmt; } void setSubStmt(Stmt *S) { SubStmt = S; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, SubStmt->getLocEnd()); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h index 48a0123..38c4c02 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h @@ -42,7 +42,6 @@ public: // below. if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { - default: llvm_unreachable("Unknown binary operator!"); case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); case BO_Mul: DISPATCH(BinMul, BinaryOperator); @@ -80,7 +79,6 @@ public: } } else if (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { - default: llvm_unreachable("Unknown unary operator!"); case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator); case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator); case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator); diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h index 371c27a..65f5460 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h @@ -15,11 +15,12 @@ #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H #define LLVM_CLANG_AST_TEMPLATEBASE_H +#include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" -#include "clang/AST/Type.h" -#include "clang/AST/TemplateName.h" namespace llvm { class FoldingSetNodeID; @@ -100,7 +101,6 @@ public: /// declaration, which is either an external declaration or a /// template declaration. TemplateArgument(Decl *D) : Kind(Declaration) { - // FIXME: Need to be sure we have the "canonical" declaration! TypeOrValue = reinterpret_cast<uintptr_t>(D); } @@ -457,7 +457,7 @@ public: } /// \brief - Fetches the full source range of the argument. - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; const TemplateArgument &getArgument() const { return Argument; @@ -589,7 +589,42 @@ struct ASTTemplateArgumentListInfo { bool &ContainsUnexpandedParameterPack); void copyInto(TemplateArgumentListInfo &List) const; static std::size_t sizeFor(unsigned NumTemplateArgs); - static std::size_t sizeFor(const TemplateArgumentListInfo &List); +}; + +/// \brief Extends ASTTemplateArgumentListInfo with the source location +/// information for the template keyword; this is used as part of the +/// representation of qualified identifiers, such as S<T>::template apply<T>. +struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo { + typedef ASTTemplateArgumentListInfo Base; + + // NOTE: the source location of the (optional) template keyword is + // stored after all template arguments. + + /// \brief Get the source location of the template keyword. + SourceLocation getTemplateKeywordLoc() const { + return *reinterpret_cast<const SourceLocation*> + (getTemplateArgs() + NumTemplateArgs); + } + + /// \brief Sets the source location of the template keyword. + void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) { + *reinterpret_cast<SourceLocation*> + (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc; + } + + static const ASTTemplateKWAndArgsInfo* + Create(ASTContext &C, SourceLocation TemplateKWLoc, + const TemplateArgumentListInfo &List); + + void initializeFrom(SourceLocation TemplateKWLoc, + const TemplateArgumentListInfo &List); + void initializeFrom(SourceLocation TemplateKWLoc, + const TemplateArgumentListInfo &List, + bool &Dependent, bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack); + void initializeFrom(SourceLocation TemplateKWLoc); + + static std::size_t sizeFor(unsigned NumTemplateArgs); }; const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h index dd9aa56..7bd367c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Type.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h @@ -95,7 +95,7 @@ namespace clang { class ExtQualsTypeCommonBase; struct PrintingPolicy; - template <typename> class CanQual; + template <typename> class CanQual; typedef CanQual<Type> CanQualType; // Provide forward declarations for all of the *Type classes @@ -236,7 +236,7 @@ public: qs.removeObjCGCAttr(); return qs; } - Qualifiers withoutObjCGLifetime() const { + Qualifiers withoutObjCLifetime() const { Qualifiers qs = *this; qs.removeObjCLifetime(); return qs; @@ -252,7 +252,8 @@ public: void removeObjCLifetime() { setObjCLifetime(OCL_None); } void addObjCLifetime(ObjCLifetime type) { assert(type); - setObjCLifetime(type); + assert(!hasObjCLifetime()); + Mask |= (type << LifetimeShift); } /// True if the lifetime is neither None or ExplicitNone. @@ -266,7 +267,7 @@ public: ObjCLifetime lifetime = getObjCLifetime(); return (lifetime == OCL_Strong || lifetime == OCL_Weak); } - + bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } void setAddressSpace(unsigned space) { @@ -346,7 +347,7 @@ public: /// Generally this answers the question of whether an object with the other /// qualifiers can be safely used as an object with these qualifiers. bool compatiblyIncludes(Qualifiers other) const { - return + return // Address spaces must match exactly. getAddressSpace() == other.getAddressSpace() && // ObjC GC qualifiers can match, be added, or be removed, but can't be @@ -363,24 +364,24 @@ public: /// qualifiers from the narrow perspective of Objective-C ARC lifetime. /// /// One set of Objective-C lifetime qualifiers compatibly includes the other - /// if the lifetime qualifiers match, or if both are non-__weak and the + /// if the lifetime qualifiers match, or if both are non-__weak and the /// including set also contains the 'const' qualifier. bool compatiblyIncludesObjCLifetime(Qualifiers other) const { if (getObjCLifetime() == other.getObjCLifetime()) return true; - + if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak) return false; - + return hasConst(); } - + bool isSupersetOf(Qualifiers Other) const; /// \brief Determine whether this set of qualifiers is a strict superset of /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; - + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } @@ -397,7 +398,7 @@ public: L += R; return L; } - + Qualifiers &operator-=(Qualifiers R) { Mask = Mask & ~(R.Mask); return *this; @@ -408,7 +409,7 @@ public: L -= R; return L; } - + std::string getAsString() const; std::string getAsString(const PrintingPolicy &Policy) const { std::string Buffer; @@ -447,7 +448,32 @@ enum CallingConv { CC_AAPCS_VFP // __attribute__((pcs("aapcs-vfp"))) }; -typedef std::pair<const Type*, Qualifiers> SplitQualType; +/// A std::pair-like structure for storing a qualified type split +/// into its local qualifiers and its locally-unqualified type. +struct SplitQualType { + /// The locally-unqualified type. + const Type *Ty; + + /// The local qualifiers. + Qualifiers Quals; + + SplitQualType() : Ty(0), Quals() {} + SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} + + SplitQualType getSingleStepDesugaredType() const; // end of this file + + // Make llvm::tie work. + operator std::pair<const Type *,Qualifiers>() const { + return std::pair<const Type *,Qualifiers>(Ty, Quals); + } + + friend bool operator==(SplitQualType a, SplitQualType b) { + return a.Ty == b.Ty && a.Quals == b.Quals; + } + friend bool operator!=(SplitQualType a, SplitQualType b) { + return a.Ty != b.Ty || a.Quals != b.Quals; + } +}; /// QualType - For efficiency, we don't store CV-qualified types as nodes on /// their own: instead each reference to a type stores the qualifiers. This @@ -501,7 +527,7 @@ public: /// This function requires that the type not be NULL. If the type might be /// NULL, use the (slightly less efficient) \c getTypePtrOrNull(). const Type *getTypePtr() const; - + const Type *getTypePtrOrNull() const; /// Retrieves a pointer to the name of the base type. @@ -534,27 +560,27 @@ public: return Value.getPointer().isNull(); } - /// \brief Determine whether this particular QualType instance has the + /// \brief Determine whether this particular QualType instance has the /// "const" qualifier set, without looking through typedefs that may have /// added "const" at a different level. bool isLocalConstQualified() const { return (getLocalFastQualifiers() & Qualifiers::Const); } - + /// \brief Determine whether this type is const-qualified. bool isConstQualified() const; - - /// \brief Determine whether this particular QualType instance has the + + /// \brief Determine whether this particular QualType instance has the /// "restrict" qualifier set, without looking through typedefs that may have /// added "restrict" at a different level. bool isLocalRestrictQualified() const { return (getLocalFastQualifiers() & Qualifiers::Restrict); } - + /// \brief Determine whether this type is restrict-qualified. bool isRestrictQualified() const; - - /// \brief Determine whether this particular QualType instance has the + + /// \brief Determine whether this particular QualType instance has the /// "volatile" qualifier set, without looking through typedefs that may have /// added "volatile" at a different level. bool isLocalVolatileQualified() const { @@ -563,9 +589,9 @@ public: /// \brief Determine whether this type is volatile-qualified. bool isVolatileQualified() const; - + /// \brief Determine whether this particular QualType instance has any - /// qualifiers, without looking through any typedefs that might add + /// qualifiers, without looking through any typedefs that might add /// qualifiers at a different level. bool hasLocalQualifiers() const { return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); @@ -573,7 +599,7 @@ public: /// \brief Determine whether this type has any qualifiers. bool hasQualifiers() const; - + /// \brief Determine whether this particular QualType instance has any /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType /// instance. @@ -588,15 +614,15 @@ public: /// \brief Retrieve the set of qualifiers applied to this type. Qualifiers getQualifiers() const; - - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// local to this particular QualType instance, not including any qualifiers /// acquired through typedefs or other sugar. unsigned getLocalCVRQualifiers() const { return getLocalFastQualifiers(); } - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; @@ -612,10 +638,10 @@ public: /// compilation's language. /// (C++0x [basic.types]p9) bool isCXX11PODType(ASTContext &Context) const; - + /// isTrivialType - Return true if this is a trivial type /// (C++0x [basic.types]p9) - bool isTrivialType(ASTContext &Context) const; + bool isTrivialType(ASTContext &Context) const; /// isTriviallyCopyableType - Return true if this is a trivially /// copyable type (C++0x [basic.types]p9) @@ -624,7 +650,7 @@ public: // Don't promise in the API that anything besides 'const' can be // easily added. - /// addConst - add the specified type qualifier to this QualType. + /// addConst - add the specified type qualifier to this QualType. void addConst() { addFastQualifiers(Qualifiers::Const); } @@ -632,13 +658,21 @@ public: return withFastQualifiers(Qualifiers::Const); } - /// addVolatile - add the specified type qualifier to this QualType. + /// addVolatile - add the specified type qualifier to this QualType. void addVolatile() { addFastQualifiers(Qualifiers::Volatile); } QualType withVolatile() const { return withFastQualifiers(Qualifiers::Volatile); } + + /// Add the restrict qualifier to this QualType. + void addRestrict() { + addFastQualifiers(Qualifiers::Restrict); + } + QualType withRestrict() const { + return withFastQualifiers(Qualifiers::Restrict); + } QualType withCVRQualifiers(unsigned CVR) const { return withFastQualifiers(CVR); @@ -719,7 +753,7 @@ public: /// type. To strip qualifiers even from within an array type, use /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; - + /// \brief Determine whether this type is more qualified than the other /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; @@ -727,19 +761,19 @@ public: /// \brief Determine whether this type is at least as qualified as the other /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; - + QualType getNonReferenceType() const; /// \brief Determine the type of a (typically non-lvalue) expression with the /// specified result type. - /// + /// /// This routine should be used for expressions for which the return type is /// explicitly specified (e.g., in a cast or call) and isn't necessarily - /// an lvalue. It removes a top-level reference (since there are no + /// an lvalue. It removes a top-level reference (since there are no /// expressions of reference type) and deletes top-level cvr-qualifiers /// from non-class types (in C++) or all types (in C). QualType getNonLValueExprType(ASTContext &Context) const; - + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar @@ -757,12 +791,14 @@ public: } /// \brief Return the specified type with one level of "sugar" removed from - /// the type. + /// the type. /// /// This routine takes off the first typedef, typeof, etc. If the outer level /// of the type is already concrete, it returns it unmodified. - QualType getSingleStepDesugaredType(const ASTContext &Context) const; - + QualType getSingleStepDesugaredType(const ASTContext &Context) const { + return getSingleStepDesugaredTypeImpl(*this, Context); + } + /// IgnoreParens - Returns the specified type after dropping any /// outer-level parentheses. QualType IgnoreParens() const { @@ -783,7 +819,7 @@ public: return getAsString(split()); } static std::string getAsString(SplitQualType split) { - return getAsString(split.first, split.second); + return getAsString(split.Ty, split.Quals); } static std::string getAsString(const Type *ty, Qualifiers qs); @@ -798,7 +834,7 @@ public: } static void getAsStringInternal(SplitQualType split, std::string &out, const PrintingPolicy &policy) { - return getAsStringInternal(split.first, split.second, out, policy); + return getAsStringInternal(split.Ty, split.Quals, out, policy); } static void getAsStringInternal(const Type *ty, Qualifiers qs, std::string &out, @@ -855,7 +891,7 @@ public: return isDestructedTypeImpl(*this); } - /// \brief Determine whether expressions of the given type are forbidden + /// \brief Determine whether expressions of the given type are forbidden /// from being lvalues in C. /// /// The expression types that are forbidden to be lvalues are: @@ -870,7 +906,7 @@ public: /// \brief Determine whether this type has trivial copy/move-assignment /// semantics. bool hasTrivialAssignment(ASTContext &Context, bool Copying) const; - + private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the @@ -879,6 +915,8 @@ private: static QualType getDesugaredType(QualType T, const ASTContext &Context); static SplitQualType getSplitDesugaredType(QualType T); static SplitQualType getSplitUnqualifiedTypeImpl(QualType type); + static QualType getSingleStepDesugaredTypeImpl(QualType type, + const ASTContext &C); static QualType IgnoreParens(QualType T); static DestructionKind isDestructedTypeImpl(QualType type); }; @@ -915,7 +953,7 @@ public: namespace clang { -/// \brief Base class that is common to both the \c ExtQuals and \c Type +/// \brief Base class that is common to both the \c ExtQuals and \c Type /// classes, which allows \c QualType to access the common fields between the /// two. /// @@ -926,7 +964,7 @@ class ExtQualsTypeCommonBase { /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or /// a self-referential pointer (for \c Type). /// - /// This pointer allows an efficient mapping from a QualType to its + /// This pointer allows an efficient mapping from a QualType to its /// underlying type pointer. const Type *const BaseType; @@ -937,14 +975,14 @@ class ExtQualsTypeCommonBase { friend class Type; friend class ExtQuals; }; - + /// ExtQuals - We can encode up to four bits in the low bits of a /// type pointer, but there are many more type qualifiers that we want /// to be able to apply to an arbitrary type. Therefore we have this /// struct, intended to be heap-allocated and used by QualType to /// store qualifiers. /// -/// The current design tags the 'const', 'restrict', and 'volatile' qualifiers +/// The current design tags the 'const', 'restrict', and 'volatile' qualifiers /// in three low bits on the QualType pointer; a fourth bit records whether /// the pointer is an ExtQuals node. The extended qualifiers (address spaces, /// Objective-C GC attributes) are much more rare. @@ -969,7 +1007,7 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { ExtQuals *this_() { return this; } public: - ExtQuals(const Type *baseType, QualType canon, Qualifiers quals) + ExtQuals(const Type *baseType, QualType canon, Qualifiers quals) : ExtQualsTypeCommonBase(baseType, canon.isNull() ? QualType(this_(), 0) : canon), Quals(quals) @@ -1008,8 +1046,8 @@ public: } }; -/// \brief The kind of C++0x ref-qualifier associated with a function type, -/// which determines whether a member function's "this" object can be an +/// \brief The kind of C++0x ref-qualifier associated with a function type, +/// which determines whether a member function's "this" object can be an /// lvalue, rvalue, or neither. enum RefQualifierKind { /// \brief No ref-qualifier was provided. @@ -1019,7 +1057,7 @@ enum RefQualifierKind { /// \brief An rvalue ref-qualifier was provided (\c &&). RQ_RValue }; - + /// Type - This is the base class of the type hierarchy. A central concept /// with types is that each type always has a canonical type. A canonical type /// is the type with any typedef names stripped out of it or the types it @@ -1071,29 +1109,32 @@ private: /// Note that this should stay at the end of the ivars for Type so that /// subclasses can pack their bitfields into the same word. unsigned Dependent : 1; - - /// \brief Whether this type somehow involves a template parameter, even + + /// \brief Whether this type somehow involves a template parameter, even /// if the resolution of the type does not depend on a template parameter. unsigned InstantiationDependent : 1; - + /// \brief Whether this type is a variably-modified type (C99 6.7.5). unsigned VariablyModified : 1; /// \brief Whether this type contains an unexpanded parameter pack /// (for C++0x variadic templates). unsigned ContainsUnexpandedParameterPack : 1; - + /// \brief Nonzero if the cache (i.e. the bitfields here starting /// with 'Cache') is valid. If so, then this is a /// LangOptions::VisibilityMode+1. mutable unsigned CacheValidAndVisibility : 2; - + + /// \brief True if the visibility was set explicitly in the source code. + mutable unsigned CachedExplicitVisibility : 1; + /// \brief Linkage of this type. mutable unsigned CachedLinkage : 2; - /// \brief Whether this type involves and local or unnamed types. + /// \brief Whether this type involves and local or unnamed types. mutable unsigned CachedLocalOrUnnamed : 1; - + /// \brief FromAST - Whether this type comes from an AST file. mutable unsigned FromAST : 1; @@ -1104,6 +1145,10 @@ private: assert(isCacheValid() && "getting linkage from invalid cache"); return static_cast<Visibility>(CacheValidAndVisibility-1); } + bool isVisibilityExplicit() const { + assert(isCacheValid() && "getting linkage from invalid cache"); + return CachedExplicitVisibility; + } Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); return static_cast<Linkage>(CachedLinkage); @@ -1113,7 +1158,7 @@ private: return CachedLocalOrUnnamed; } }; - enum { NumTypeBits = 18 }; + enum { NumTypeBits = 19 }; protected: // These classes allow subclasses to somewhat cleanly pack bitfields @@ -1152,9 +1197,6 @@ protected: /// regparm and the calling convention. unsigned ExtInfo : 8; - /// Whether the function is variadic. Only used by FunctionProtoType. - unsigned Variadic : 1; - /// TypeQuals - Used only by FunctionProtoType, put here to pack with the /// other bitfields. /// The qualifiers are part of FunctionProtoType because... @@ -1162,7 +1204,7 @@ protected: /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. unsigned TypeQuals : 3; - + /// \brief The ref-qualifier associated with a \c FunctionProtoType. /// /// This is a value of type \c RefQualifierKind. @@ -1247,7 +1289,7 @@ protected: private: /// \brief Set whether this type comes from an AST file. - void setFromAST(bool V = true) const { + void setFromAST(bool V = true) const { TypeBits.FromAST = V; } @@ -1256,7 +1298,7 @@ private: protected: // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } - Type(TypeClass tc, QualType canon, bool Dependent, + Type(TypeClass tc, QualType canon, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) : ExtQualsTypeCommonBase(this, @@ -1267,20 +1309,21 @@ protected: TypeBits.VariablyModified = VariablyModified; TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; TypeBits.CacheValidAndVisibility = 0; + TypeBits.CachedExplicitVisibility = false; TypeBits.CachedLocalOrUnnamed = false; TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; } friend class ASTContext; - void setDependent(bool D = true) { - TypeBits.Dependent = D; + void setDependent(bool D = true) { + TypeBits.Dependent = D; if (D) TypeBits.InstantiationDependent = true; } - void setInstantiationDependent(bool D = true) { + void setInstantiationDependent(bool D = true) { TypeBits.InstantiationDependent = D; } - void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; + void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } void setContainsUnexpandedParameterPack(bool PP = true) { TypeBits.ContainsUnexpandedParameterPack = PP; @@ -1306,8 +1349,8 @@ public: /// }; /// \endcode /// - /// Note that this routine does not specify which - bool containsUnexpandedParameterPack() const { + /// Note that this routine does not specify which + bool containsUnexpandedParameterPack() const { return TypeBits.ContainsUnexpandedParameterPack; } @@ -1317,6 +1360,11 @@ public: return CanonicalType == QualType(this, 0); } + /// Pull a single level of sugar off of this locally-unqualified type. + /// Users should generally prefer SplitQualType::getSingleStepDesugaredType() + /// or QualType::getSingleStepDesugaredType(const ASTContext&). + QualType getLocallyUnqualifiedSingleStepDesugaredType() const; + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. @@ -1324,18 +1372,22 @@ public: /// A type that can describe objects, but which lacks information needed to /// determine its size (e.g. void, or a fwd declared struct). Clients of this /// routine will need to determine if the size is actually required. - bool isIncompleteType() const; + /// + /// \brief Def If non-NULL, and the type refers to some kind of declaration + /// that can be completed (such as a C struct, C++ class, or Objective-C + /// class), will be set to the declaration. + bool isIncompleteType(NamedDecl **Def = 0) const; /// isIncompleteOrObjectType - Return true if this is an incomplete or object /// type, in other words, not a function type. bool isIncompleteOrObjectType() const { return !isFunctionType(); } - + /// \brief Determine whether this type is an object type. bool isObjectType() const { // C++ [basic.types]p8: - // An object type is a (possibly cv-qualified) type that is not a + // An object type is a (possibly cv-qualified) type that is not a // function type, not a reference type, and not a void type. return !isReferenceType() && !isFunctionType() && !isVoidType(); } @@ -1367,6 +1419,10 @@ public: /// isSpecificPlaceholderType - Test for a specific placeholder type. bool isSpecificPlaceholderType(unsigned K) const; + /// isNonOverloadPlaceholderType - Test for a placeholder type + /// other than Overload; see BuiltinType::isNonOverloadPlaceholderType. + bool isNonOverloadPlaceholderType() const; + /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) @@ -1378,13 +1434,13 @@ public: bool isChar32Type() const; bool isAnyCharacterType() const; bool isIntegralType(ASTContext &Ctx) const; - + /// \brief Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; /// \brief Determine whether this type is an integral or unscoped enumeration /// type. bool isIntegralOrUnscopedEnumerationType() const; - + /// Floating point categories. bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) /// isComplexType() does *not* include complex integers (a GCC extension). @@ -1451,7 +1507,7 @@ public: bool isCARCBridgableType() const; bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t - bool isAtomicType() const; // C1X _Atomic() + bool isAtomicType() const; // C11 _Atomic() /// Determines if this type, which must satisfy /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather @@ -1479,32 +1535,32 @@ public: /// that its definition somehow depends on a template parameter /// (C++ [temp.dep.type]). bool isDependentType() const { return TypeBits.Dependent; } - + /// \brief Determine whether this type is an instantiation-dependent type, /// meaning that the type involves a template parameter (even if the /// definition does not actually depend on the type substituted for that /// template parameter). - bool isInstantiationDependentType() const { - return TypeBits.InstantiationDependent; + bool isInstantiationDependentType() const { + return TypeBits.InstantiationDependent; } - + /// \brief Whether this type is a variably-modified type (C99 6.7.5). bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } /// \brief Whether this type involves a variable-length array type /// with a definite size. bool hasSizedVLAType() const; - + /// \brief Whether this type is or contains a local or unnamed type. bool hasUnnamedOrLocalType() const; - + bool isOverloadableType() const; /// \brief Determine wither this type is a C++ elaborated-type-specifier. bool isElaboratedTypeSpecifier() const; bool canDecayToPointerType() const; - + /// hasPointerRepresentation - Whether this type is represented /// natively as a pointer; this includes pointers, references, block /// pointers, and Objective-C interface, qualified id, and qualified @@ -1547,7 +1603,7 @@ public: const CXXRecordDecl *getCXXRecordDeclForPointerType() const; /// \brief Retrieves the CXXRecordDecl that this type refers to, either - /// because the type is a RecordType or because it is the injected-class-name + /// because the type is a RecordType or because it is the injected-class-name /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; @@ -1555,7 +1611,7 @@ public: /// an initializer of this type. This looks through declarators like pointer /// types, but not through decltype or typedefs. AutoType *getContainedAutoType() const; - + /// Member-template getAs<specific type>'. Look through sugar for /// an instance of <specific type>. This scheme will eventually /// replace the specific getAsXXXX methods above. @@ -1608,15 +1664,15 @@ public: bool isSignedIntegerType() const; /// isUnsignedIntegerType - Return true if this is an integer type that is - /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], + /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], /// or an enum decl which has an unsigned representation. bool isUnsignedIntegerType() const; - /// Determines whether this is an integer type that is signed or an + /// Determines whether this is an integer type that is signed or an /// enumeration types whose underlying type is a signed integer type. bool isSignedIntegerOrEnumerationType() const; - - /// Determines whether this is an integer type that is unsigned or an + + /// Determines whether this is an integer type that is unsigned or an /// enumeration types whose underlying type is a unsigned integer type. bool isUnsignedIntegerOrEnumerationType() const; @@ -1635,19 +1691,22 @@ public: /// \brief Determine the visibility of this type. Visibility getVisibility() const; + /// \brief Return true if the visibility was explicitly set is the code. + bool isVisibilityExplicit() const; + /// \brief Determine the linkage and visibility of this type. std::pair<Linkage,Visibility> getLinkageAndVisibility() const; - + /// \brief Note that the linkage is no longer known. void ClearLinkageCache(); - + const char *getTypeClassName() const; QualType getCanonicalTypeInternal() const { return CanonicalType; } CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h - void dump() const; + LLVM_ATTRIBUTE_USED void dump() const; static bool classof(const Type *) { return true; } @@ -1677,81 +1736,9 @@ template <> inline const Class##Type *Type::castAs() const { \ class BuiltinType : public Type { public: enum Kind { - Void, - - Bool, // This is bool and/or _Bool. - Char_U, // This is 'char' for targets where char is unsigned. - UChar, // This is explicitly qualified unsigned char. - WChar_U, // This is 'wchar_t' for C++, when unsigned. - Char16, // This is 'char16_t' for C++. - Char32, // This is 'char32_t' for C++. - UShort, - UInt, - ULong, - ULongLong, - UInt128, // __uint128_t - - Char_S, // This is 'char' for targets where char is signed. - SChar, // This is explicitly qualified signed char. - WChar_S, // This is 'wchar_t' for C++, when signed. - Short, - Int, - Long, - LongLong, - Int128, // __int128_t - - Half, // This is the 'half' type in OpenCL, - // __fp16 in case of ARM NEON. - Float, Double, LongDouble, - - NullPtr, // This is the type of C++0x 'nullptr'. - - /// The primitive Objective C 'id' type. The user-visible 'id' - /// type is a typedef of an ObjCObjectPointerType to an - /// ObjCObjectType with this as its base. In fact, this only ever - /// shows up in an AST as the base type of an ObjCObjectType. - ObjCId, - - /// The primitive Objective C 'Class' type. The user-visible - /// 'Class' type is a typedef of an ObjCObjectPointerType to an - /// ObjCObjectType with this as its base. In fact, this only ever - /// shows up in an AST as the base type of an ObjCObjectType. - ObjCClass, - - /// The primitive Objective C 'SEL' type. The user-visible 'SEL' - /// type is a typedef of a PointerType to this. - ObjCSel, - - /// This represents the type of an expression whose type is - /// totally unknown, e.g. 'T::foo'. It is permitted for this to - /// appear in situations where the structure of the type is - /// theoretically deducible. - Dependent, - - /// The type of an unresolved overload set. A placeholder type. - /// Expressions with this type have one of the following basic - /// forms, with parentheses generally permitted: - /// foo # possibly qualified, not if an implicit access - /// foo # possibly qualified, not if an implicit access - /// &foo # possibly qualified, not if an implicit access - /// x->foo # only if might be a static member function - /// &x->foo # only if might be a static member function - /// &Class::foo # when a pointer-to-member; sub-expr also has this type - /// OverloadExpr::find can be used to analyze the expression. - Overload, - - /// The type of a bound C++ non-static member function. - /// A placeholder type. Expressions with this type have one of the - /// following basic forms: - /// foo # if an implicit access - /// x->foo # if only contains non-static members - BoundMember, - - /// __builtin_any_type. A placeholder type. Useful for clients - /// like debuggers that don't know what type to give something. - /// Only a small number of operations are valid on expressions of - /// unknown type, most notably explicit casts. - UnknownAny +#define BUILTIN_TYPE(Id, SingletonId) Id, +#define LAST_BUILTIN_TYPE(Id) LastKind = Id +#include "clang/AST/BuiltinTypes.def" }; public: @@ -1785,11 +1772,29 @@ public: return getKind() >= Half && getKind() <= LongDouble; } + /// Determines whether the given kind corresponds to a placeholder type. + static bool isPlaceholderTypeKind(Kind K) { + return K >= Overload; + } + /// Determines whether this type is a placeholder type, i.e. a type /// which cannot appear in arbitrary positions in a fully-formed /// expression. bool isPlaceholderType() const { - return getKind() >= Overload; + return isPlaceholderTypeKind(getKind()); + } + + /// Determines whether this type is a placeholder type other than + /// Overload. Most placeholder types require only syntactic + /// information about their context in order to be resolved (e.g. + /// whether it is a call expression), which means they can (and + /// should) be resolved in an earlier "phase" of analysis. + /// Overload expressions sometimes pick up further information + /// from their context, like whether the context expects a + /// specific function-pointer type, and so frequently need + /// special treatment. + bool isNonOverloadPlaceholderType() const { + return getKind() > Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -1868,7 +1873,7 @@ class PointerType : public Type, public llvm::FoldingSetNode { Type(Pointer, CanonicalPtr, Pointee->isDependentType(), Pointee->isInstantiationDependentType(), Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), + Pointee->containsUnexpandedParameterPack()), PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. @@ -1905,7 +1910,7 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. - + public: // Get the pointee type. Pointee is required to always be a function type. @@ -1938,17 +1943,17 @@ protected: Type(tc, CanonicalRef, Referencee->isDependentType(), Referencee->isInstantiationDependentType(), Referencee->isVariablyModifiedType(), - Referencee->containsUnexpandedParameterPack()), - PointeeType(Referencee) + Referencee->containsUnexpandedParameterPack()), + PointeeType(Referencee) { ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); } - + public: bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; } bool isInnerRef() const { return ReferenceTypeBits.InnerRef; } - + QualType getPointeeTypeAsWritten() const { return PointeeType; } QualType getPointeeType() const { // FIXME: this might strip inner qualifiers; okay? @@ -2021,15 +2026,15 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : Type(MemberPointer, CanonicalPtr, Cls->isDependentType() || Pointee->isDependentType(), - (Cls->isInstantiationDependentType() || + (Cls->isInstantiationDependentType() || Pointee->isInstantiationDependentType()), Pointee->isVariablyModifiedType(), - (Cls->containsUnexpandedParameterPack() || + (Cls->containsUnexpandedParameterPack() || Pointee->containsUnexpandedParameterPack())), PointeeType(Pointee), Class(Cls) { } friend class ASTContext; // ASTContext creates these. - + public: QualType getPointeeType() const { return PointeeType; } @@ -2136,7 +2141,7 @@ class ConstantArrayType : public ArrayType { protected: ConstantArrayType(TypeClass tc, QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), + : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), Size(size) {} friend class ASTContext; // ASTContext creates these. public: @@ -2144,17 +2149,17 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - + /// \brief Determine the number of bits required to address a member of // an array with the given element type and number of elements. static unsigned getNumAddressingBits(ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements); - + /// \brief Determine the maximum number of active bits that an array's size /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(ASTContext &Context); - + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSize(), getSizeModifier(), getIndexTypeCVRQualifiers()); @@ -2180,7 +2185,7 @@ class IncompleteArrayType : public ArrayType { IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, + : ArrayType(IncompleteArray, et, can, sm, tq, et->containsUnexpandedParameterPack()) {} friend class ASTContext; // ASTContext creates these. public: @@ -2232,7 +2237,7 @@ class VariableArrayType : public ArrayType { VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, + : ArrayType(VariableArray, et, can, sm, tq, et->containsUnexpandedParameterPack()), SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. @@ -2388,12 +2393,12 @@ protected: VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind); - + VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind); friend class ASTContext; // ASTContext creates these. - + public: QualType getElementType() const { return ElementType; } @@ -2559,7 +2564,7 @@ class FunctionType : public Type { bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } - unsigned getRegParm() const { + unsigned getRegParm() const { unsigned RegParm = Bits >> RegParmOffset; if (RegParm > 0) --RegParm; @@ -2607,23 +2612,21 @@ class FunctionType : public Type { }; protected: - FunctionType(TypeClass tc, QualType res, bool variadic, + FunctionType(TypeClass tc, QualType res, unsigned typeQuals, RefQualifierKind RefQualifier, QualType Canonical, bool Dependent, bool InstantiationDependent, - bool VariablyModified, bool ContainsUnexpandedParameterPack, + bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack), + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; - FunctionTypeBits.Variadic = variadic; FunctionTypeBits.TypeQuals = typeQuals; FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier); } - bool isVariadic() const { return FunctionTypeBits.Variadic; } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } - + RefQualifierKind getRefQualifier() const { return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } @@ -2640,7 +2643,7 @@ public: /// \brief Determine the type of an expression that calls a function of /// this type. - QualType getCallResultType(ASTContext &Context) const { + QualType getCallResultType(ASTContext &Context) const { return getResultType().getNonLValueExprType(Context); } @@ -2657,13 +2660,13 @@ public: /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical, + : FunctionType(FunctionNoProto, Result, 0, RQ_None, Canonical, /*Dependent=*/false, /*InstantiationDependent=*/false, - Result->isVariablyModifiedType(), + Result->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false, Info) {} friend class ASTContext; // ASTContext creates these. - + public: // No additional state past what FunctionType provides. @@ -2695,34 +2698,26 @@ public: /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : - Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0), - RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0), - ConsumedArguments(0) {} + Variadic(false), HasTrailingReturn(false), TypeQuals(0), + ExceptionSpecType(EST_None), RefQualifier(RQ_None), + NumExceptions(0), Exceptions(0), NoexceptExpr(0), ConsumedArguments(0) {} FunctionType::ExtInfo ExtInfo; - bool Variadic; - ExceptionSpecificationType ExceptionSpecType; + bool Variadic : 1; + bool HasTrailingReturn : 1; unsigned char TypeQuals; + ExceptionSpecificationType ExceptionSpecType; RefQualifierKind RefQualifier; unsigned NumExceptions; - - /// Exceptions - A variable size array after that holds the exception types. const QualType *Exceptions; - - /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* - /// pointing to the expression in the noexcept() specifier. Expr *NoexceptExpr; - - /// ConsumedArgs - A variable size array, following Exceptions - /// and of length NumArgs, holding flags indicating which arguments - /// are consumed. This only appears if HasAnyConsumedArgs is true. const bool *ConsumedArguments; }; private: /// \brief Determine whether there are any argument types that /// contain an unexpanded parameter pack. - static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, + static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, unsigned numArgs) { for (unsigned Idx = 0; Idx < numArgs; ++Idx) if (ArgArray[Idx]->containsUnexpandedParameterPack()) @@ -2735,7 +2730,7 @@ private: QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. - unsigned NumArgs : 19; + unsigned NumArgs : 17; /// NumExceptions - The number of types in the exception spec, if any. unsigned NumExceptions : 9; @@ -2746,6 +2741,25 @@ private: /// HasAnyConsumedArgs - Whether this function has any consumed arguments. unsigned HasAnyConsumedArgs : 1; + /// Variadic - Whether the function is variadic. + unsigned Variadic : 1; + + /// HasTrailingReturn - Whether this function has a trailing return type. + unsigned HasTrailingReturn : 1; + + // ArgInfo - There is an variable size array after the class in memory that + // holds the argument types. + + // Exceptions - There is another variable size array after ArgInfo that + // holds the exception types. + + // NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing + // to the expression in the noexcept() specifier. + + // ConsumedArgs - A variable size array, following Exceptions + // and of length NumArgs, holding flags indicating which arguments + // are consumed. This only appears if HasAnyConsumedArgs is true. + friend class ASTContext; // ASTContext creates these. const bool *getConsumedArgsBuffer() const { @@ -2772,6 +2786,7 @@ public: ExtProtoInfo EPI; EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); + EPI.HasTrailingReturn = hasTrailingReturn(); EPI.ExceptionSpecType = getExceptionSpecType(); EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); @@ -2833,24 +2848,26 @@ public: return getNoexceptSpec(Ctx) == NR_Nothrow; } - using FunctionType::isVariadic; + bool isVariadic() const { return Variadic; } /// \brief Determines whether this function prototype contains a /// parameter pack at the end. /// /// A function template whose last parameter is a parameter pack can be /// called with an arbitrary number of arguments, much like a variadic - /// function. However, + /// function. bool isTemplateVariadic() const; - + + bool hasTrailingReturn() const { return HasTrailingReturn; } + unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } - + /// \brief Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { return FunctionType::getRefQualifier(); } - + typedef const QualType *arg_type_iterator; arg_type_iterator arg_type_begin() const { return reinterpret_cast<const QualType *>(this+1); @@ -2881,6 +2898,9 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + void printExceptionSpecification(std::string &S, + PrintingPolicy Policy) const; + static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; } @@ -2901,7 +2921,7 @@ class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, true, false, + : Type(UnresolvedUsing, QualType(), true, true, false, /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. @@ -2931,9 +2951,9 @@ class TypedefType : public Type { TypedefNameDecl *Decl; protected: TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), + : Type(tc, can, can->isDependentType(), can->isInstantiationDependentType(), - can->isVariablyModifiedType(), + can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); @@ -2996,10 +3016,10 @@ public: class TypeOfType : public Type { QualType TOType; TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), + : Type(TypeOf, can, T->isDependentType(), T->isInstantiationDependentType(), - T->isVariablyModifiedType(), - T->containsUnexpandedParameterPack()), + T->isVariablyModifiedType(), + T->containsUnexpandedParameterPack()), TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } @@ -3020,10 +3040,6 @@ public: /// DecltypeType (C++0x) class DecltypeType : public Type { Expr *E; - - // FIXME: We could get rid of UnderlyingType if we wanted to: We would have to - // Move getDesugaredType to ASTContext so that it can call getDecltypeForExpr - // from it. QualType UnderlyingType; protected: @@ -3089,7 +3105,7 @@ public: QualType getBaseType() const { return BaseType; } UTTKind getUTTKind() const { return UKind; } - + static bool classof(const Type *T) { return T->getTypeClass() == UnaryTransform; } @@ -3101,6 +3117,8 @@ class TagType : public Type { /// TagDecl that declares the entity. TagDecl * decl; + friend class ASTReader; + protected: TagType(TypeClass TC, const TagDecl *D, QualType can); @@ -3115,8 +3133,6 @@ public: return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } static bool classof(const TagType *) { return true; } - static bool classof(const RecordType *) { return true; } - static bool classof(const EnumType *) { return true; } }; /// RecordType - This is a helper class that allows the use of isa/cast/dyncast @@ -3142,10 +3158,7 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - static bool classof(const TagType *T); - static bool classof(const Type *T) { - return isa<TagType>(T) && classof(cast<TagType>(T)); - } + static bool classof(const Type *T) { return T->getTypeClass() == Record; } static bool classof(const RecordType *) { return true; } }; @@ -3164,10 +3177,7 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - static bool classof(const TagType *T); - static bool classof(const Type *T) { - return isa<TagType>(T) && classof(cast<TagType>(T)); - } + static bool classof(const Type *T) { return T->getTypeClass() == Enum; } static bool classof(const EnumType *) { return true; } }; @@ -3284,7 +3294,7 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), + : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, /*InstantiationDependent=*/true, /*VariablyModified=*/false, PP) { @@ -3389,7 +3399,7 @@ public: /// /// When a pack expansion in the source code contains multiple parameter packs /// and those parameter packs correspond to different levels of template -/// parameter lists, this type node is used to represent a template type +/// parameter lists, this type node is used to represent a template type /// parameter pack from an outer level, which has already had its argument pack /// substituted but that still lives within a pack expansion that itself /// could not be instantiated. When actually performing a substitution into @@ -3399,38 +3409,38 @@ public: class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { /// \brief The original type parameter. const TemplateTypeParmType *Replaced; - + /// \brief A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - + /// \brief The number of template arguments in \c Arguments. unsigned NumArguments; - - SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, + + SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, const TemplateArgument &ArgPack); - + friend class ASTContext; - + public: IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } - + /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { return Replaced; } - + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - + TemplateArgument getArgumentPack() const; - + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const TemplateTypeParmType *Replaced, const TemplateArgument &ArgPack); - + static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParmPack; } @@ -3513,8 +3523,12 @@ class TemplateSpecializationType /// \brief - The number of template arguments named in this class /// template specialization. - unsigned NumArgs; + unsigned NumArgs : 31; + /// \brief Whether this template specialization type is a substituted + /// type alias. + bool TypeAlias : 1; + TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon, @@ -3556,9 +3570,23 @@ public: return isa<InjectedClassNameType>(getCanonicalTypeInternal()); } - /// True if this template specialization type is for a type alias - /// template. - bool isTypeAlias() const; + /// \brief Determine if this template specialization type is for a type alias + /// template that has been substituted. + /// + /// Nearly every template specialization type whose template is an alias + /// template will be substituted. However, this is not the case when + /// the specialization contains a pack expansion but the template alias + /// does not have a corresponding parameter pack, e.g., + /// + /// \code + /// template<typename T, typename U, typename V> struct S; + /// template<typename T, typename U> using A = S<T, int, U>; + /// template<typename... Ts> struct X { + /// typedef A<Ts...> type; // not a type alias + /// }; + /// \endcode + bool isTypeAlias() const { return TypeAlias; } + /// Get the aliased type, if this is a specialization of a type alias /// template. QualType getAliasedType() const { @@ -3646,7 +3674,7 @@ class InjectedClassNameType : public Type { InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), /*Dependent=*/true, /*InstantiationDependent=*/true, - /*VariablyModified=*/false, + /*VariablyModified=*/false, /*ContainsUnexpandedParameterPack=*/false), Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); @@ -3708,10 +3736,10 @@ enum ElaboratedTypeKeyword { class TypeWithKeyword : public Type { protected: TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, - QualType Canonical, bool Dependent, - bool InstantiationDependent, bool VariablyModified, + QualType Canonical, bool Dependent, + bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, ContainsUnexpandedParameterPack) { TypeWithKeywordBits.Keyword = Keyword; } @@ -3815,12 +3843,12 @@ public: }; /// \brief Represents a qualified type name for which the type name is -/// dependent. +/// dependent. /// -/// DependentNameType represents a class of dependent types that involve a -/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) +/// DependentNameType represents a class of dependent types that involve a +/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) /// name of a type. The DependentNameType may start with a "typename" (for a -/// typename-specifier), "class", "struct", "union", or "enum" (for a +/// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { @@ -3831,7 +3859,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The type that this typename specifier refers to. const IdentifierInfo *Name; - DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, /*InstantiationDependent=*/true, @@ -3948,7 +3976,7 @@ public: } static bool classof(const DependentTemplateSpecializationType *T) { return true; - } + } }; /// \brief Represents a pack expansion of types. @@ -3965,7 +3993,7 @@ public: /// \code /// template<typename ...Types> struct tuple; /// -/// template<typename ...Types> +/// template<typename ...Types> /// struct tuple_of_references { /// typedef tuple<Types&...> type; /// }; @@ -3978,24 +4006,24 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { QualType Pattern; /// \brief The number of expansions that this pack expansion will - /// generate when substituted (+1), or indicates that + /// generate when substituted (+1), or indicates that /// - /// This field will only have a non-zero value when some of the parameter - /// packs that occur within the pattern have been substituted but others have + /// This field will only have a non-zero value when some of the parameter + /// packs that occur within the pattern have been substituted but others have /// not. unsigned NumExpansions; - + PackExpansionType(QualType Pattern, QualType Canon, llvm::Optional<unsigned> NumExpansions) : Type(PackExpansion, Canon, /*Dependent=*/true, /*InstantiationDependent=*/true, /*VariableModified=*/Pattern->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), - Pattern(Pattern), + Pattern(Pattern), NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } friend class ASTContext; // ASTContext creates these - + public: /// \brief Retrieve the pattern of this pack expansion, which is the /// type that will be repeatedly instantiated when instantiating the @@ -4007,10 +4035,10 @@ public: llvm::Optional<unsigned> getNumExpansions() const { if (NumExpansions) return NumExpansions - 1; - + return llvm::Optional<unsigned>(); } - + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -4031,7 +4059,7 @@ public: } static bool classof(const PackExpansionType *T) { return true; - } + } }; /// ObjCObjectType - Represents a class type in Objective C. @@ -4075,7 +4103,7 @@ class ObjCObjectType : public Type { ObjCProtocolDecl **getProtocolStorage(); protected: - ObjCObjectType(QualType Canonical, QualType Base, + ObjCObjectType(QualType Canonical, QualType Base, ObjCProtocolDecl * const *Protocols, unsigned NumProtocols); enum Nonce_ObjCInterface { Nonce_ObjCInterface }; @@ -4132,7 +4160,7 @@ public: assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; } - + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -4153,7 +4181,7 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { // If anyone adds fields here, ObjCObjectType::getProtocolStorage() // will need to be modified. - ObjCObjectTypeImpl(QualType Canonical, QualType Base, + ObjCObjectTypeImpl(QualType Canonical, QualType Base, ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} @@ -4162,8 +4190,8 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType Base, - ObjCProtocolDecl *const *protocols, - unsigned NumProtocols); + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); }; inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { @@ -4185,12 +4213,14 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { /// - It is its own base type. That is, if T is an ObjCInterfaceType*, /// T->getBaseType() == QualType(T, 0). class ObjCInterfaceType : public ObjCObjectType { - ObjCInterfaceDecl *Decl; + mutable ObjCInterfaceDecl *Decl; ObjCInterfaceType(const ObjCInterfaceDecl *D) : ObjCObjectType(Nonce_ObjCInterface), Decl(const_cast<ObjCInterfaceDecl*>(D)) {} friend class ASTContext; // ASTContext creates these. + friend class ASTReader; + friend class ObjCInterfaceDecl; public: /// getDecl - Get the declaration of this interface. @@ -4300,7 +4330,7 @@ public: bool isObjCClassType() const { return getObjectType()->isObjCUnqualifiedClass(); } - + /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some /// non-empty set of protocols. bool isObjCQualifiedIdType() const { @@ -4337,7 +4367,7 @@ public: ObjCProtocolDecl *getProtocol(unsigned I) const { return getObjectType()->getProtocol(I); } - + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -4396,7 +4426,7 @@ public: addFastQualifiers(type.getLocalFastQualifiers()); if (!type.hasLocalNonFastQualifiers()) return type.getTypePtrUnsafe(); - + const ExtQuals *extQuals = type.getExtQualsUnsafe(); addConsistentQualifiers(extQuals->getQualifiers()); return extQuals->getBaseType(); @@ -4412,6 +4442,13 @@ public: // Inline function definitions. +inline SplitQualType SplitQualType::getSingleStepDesugaredType() const { + SplitQualType desugar = + Ty->getLocallyUnqualifiedSingleStepDesugaredType().split(); + desugar.Quals.addConsistentQualifiers(Quals); + return desugar; +} + inline const Type *QualType::getTypePtr() const { return getCommonPtr()->BaseType; } @@ -4463,7 +4500,7 @@ inline bool QualType::isCanonical() const { inline bool QualType::isCanonicalAsParam() const { if (!isCanonical()) return false; if (hasLocalQualifiers()) return false; - + const Type *T = getTypePtr(); if (T->isVariablyModifiedType() && T->hasSizedVLAType()) return false; @@ -4472,21 +4509,21 @@ inline bool QualType::isCanonicalAsParam() const { } inline bool QualType::isConstQualified() const { - return isLocalConstQualified() || + return isLocalConstQualified() || getCommonPtr()->CanonicalType.isLocalConstQualified(); } inline bool QualType::isRestrictQualified() const { - return isLocalRestrictQualified() || + return isLocalRestrictQualified() || getCommonPtr()->CanonicalType.isLocalRestrictQualified(); } inline bool QualType::isVolatileQualified() const { - return isLocalVolatileQualified() || + return isLocalVolatileQualified() || getCommonPtr()->CanonicalType.isLocalVolatileQualified(); } - + inline bool QualType::hasQualifiers() const { return hasLocalQualifiers() || getCommonPtr()->CanonicalType.hasLocalQualifiers(); @@ -4496,7 +4533,7 @@ inline QualType QualType::getUnqualifiedType() const { if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers()) return QualType(getTypePtr(), 0); - return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0); + return QualType(getSplitUnqualifiedTypeImpl(*this).Ty, 0); } inline SplitQualType QualType::getSplitUnqualifiedType() const { @@ -4505,7 +4542,7 @@ inline SplitQualType QualType::getSplitUnqualifiedType() const { return getSplitUnqualifiedTypeImpl(*this); } - + inline void QualType::removeLocalConst() { removeLocalFastQualifiers(Qualifiers::Const); } @@ -4616,7 +4653,8 @@ inline bool Type::isCompoundType() const { isReferenceType() || // -- classes containing a sequence of objects of various types, [...]; isRecordType() || - // -- unions, which ar classes capable of containing objects of different types at different times; + // -- unions, which are classes capable of containing objects of different + // types at different times; isUnionType() || // -- enumerations, which comprise a set of named constant values. [...]; isEnumeralType() || @@ -4706,7 +4744,7 @@ inline bool Type::isObjCObjectType() const { return isa<ObjCObjectType>(CanonicalType); } inline bool Type::isObjCObjectOrInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType) || + return isa<ObjCInterfaceType>(CanonicalType) || isa<ObjCObjectType>(CanonicalType); } inline bool Type::isAtomicType() const { @@ -4766,11 +4804,87 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { } inline bool Type::isSpecificPlaceholderType(unsigned K) const { + assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K)); if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) return (BT->getKind() == (BuiltinType::Kind) K); return false; } +inline bool Type::isNonOverloadPlaceholderType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + return BT->isNonOverloadPlaceholderType(); + return false; +} + +inline bool Type::isVoidType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Void; + return false; +} + +inline bool Type::isHalfType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Half; + // FIXME: Should we allow complex __fp16? Probably not. + return false; +} + +inline bool Type::isNullPtrType() const { + if (const BuiltinType *BT = getAs<BuiltinType>()) + return BT->getKind() == BuiltinType::NullPtr; + return false; +} + +extern bool IsEnumDeclComplete(EnumDecl *); +extern bool IsEnumDeclScoped(EnumDecl *); + +inline bool Type::isIntegerType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { + // Incomplete enum types are not treated as integer types. + // FIXME: In C++, enum types are never integer types. + return IsEnumDeclComplete(ET->getDecl()) && + !IsEnumDeclScoped(ET->getDecl()); + } + return false; +} + +inline bool Type::isScalarType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() > BuiltinType::Void && + BT->getKind() <= BuiltinType::NullPtr; + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + // Enums are scalar types, but only if they are defined. Incomplete enums + // are not treated as scalar types. + return IsEnumDeclComplete(ET->getDecl()); + return isa<PointerType>(CanonicalType) || + isa<BlockPointerType>(CanonicalType) || + isa<MemberPointerType>(CanonicalType) || + isa<ComplexType>(CanonicalType) || + isa<ObjCObjectPointerType>(CanonicalType); +} + +inline bool Type::isIntegralOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + + // Check for a complete enum type; incomplete enum types are not properly an + // enumeration type in the sense required here. + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + return IsEnumDeclComplete(ET->getDecl()); + + return false; +} + +inline bool Type::isBooleanType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Bool; + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { @@ -4822,15 +4936,15 @@ template<typename T, bool isArrayType = (llvm::is_same<T, ArrayType>::value || llvm::is_base_of<ArrayType, T>::value)> struct ArrayType_cannot_be_used_with_getAs { }; - + template<typename T> struct ArrayType_cannot_be_used_with_getAs<T, true>; - + /// Member-template getAs<specific type>'. template <typename T> const T *Type::getAs() const { ArrayType_cannot_be_used_with_getAs<T> at; (void)at; - + // If this is directly a T type, return it. if (const T *Ty = dyn_cast<T>(this)) return Ty; diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h index 20acada..aab87be 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h @@ -18,6 +18,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/TemplateBase.h" #include "clang/Basic/Specifiers.h" +#include "llvm/Support/Compiler.h" namespace clang { class ASTContext; @@ -93,9 +94,11 @@ public: SourceLocation getEndLoc() const; /// \brief Get the full source range. - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } + SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } /// \brief Get the local source range. SourceRange getLocalSourceRange() const { @@ -159,7 +162,8 @@ public: static bool classof(const TypeLoc *TL) { return true; } private: - static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc); + static void initializeImpl(ASTContext &Context, TypeLoc TL, + SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); static TypeLoc IgnoreParensImpl(TypeLoc TL); static SourceRange getLocalSourceRangeImpl(TypeLoc TL); @@ -226,7 +230,7 @@ public: /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { - return getLocalDataSize() + + return getLocalDataSize() + getFullDataSizeForType(getType().getLocalUnqualifiedType()); } @@ -326,7 +330,7 @@ protected: void *getExtraLocalData() const { return getLocalData() + 1; } - + void *getNonLocalData() const { return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize(); } @@ -392,7 +396,7 @@ struct TypeSpecLocInfo { /// \brief A reasonable base class for TypeLocs that correspond to /// types that are written as a type-specifier. -class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, +class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, TypeSpecTypeLoc, Type, TypeSpecLocInfo> { @@ -566,10 +570,11 @@ class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, public: TagDecl *getDecl() const { return getTypePtr()->getDecl(); } - /// \brief True if the tag was defined in this type specifier. + /// \brief True if the tag was defined in this type specifier. bool isDefinition() const { - return getDecl()->isCompleteDefinition() && - (getNameLoc().isInvalid() || getNameLoc() == getDecl()->getLocation()); + TagDecl *D = getDecl(); + return D->isCompleteDefinition() && + (D->getIdentifier() == 0 || D->getLocation() == getNameLoc()); } }; @@ -789,7 +794,7 @@ public: assert(i < getNumProtocols() && "Index is out of bounds!"); return *(this->getTypePtr()->qual_begin() + i); } - + bool hasBaseTypeAsWritten() const { return getLocalData()->HasBaseTypeAsWritten; } @@ -900,11 +905,11 @@ struct PointerLikeLocInfo { SourceLocation StarLoc; }; -/// A base class for +/// A base class for template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { -public: +public: SourceLocation getSigilLoc() const { return this->getLocalData()->StarLoc; } @@ -1077,6 +1082,10 @@ public: getLocalData()->TrailingReturn = Trailing; } + ArrayRef<ParmVarDecl *> getParams() const { + return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs()); + } + // ParmVarDecls* are stored after Info, one for each argument. ParmVarDecl **getParmArray() const { return (ParmVarDecl**) getExtraLocalData(); @@ -1213,6 +1222,7 @@ struct TemplateNameLocInfo { }; struct TemplateSpecializationLocInfo : TemplateNameLocInfo { + SourceLocation TemplateKWLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; }; @@ -1223,6 +1233,13 @@ class TemplateSpecializationTypeLoc : TemplateSpecializationType, TemplateSpecializationLocInfo> { public: + SourceLocation getTemplateKeywordLoc() const { + return getLocalData()->TemplateKWLoc; + } + void setTemplateKeywordLoc(SourceLocation Loc) { + getLocalData()->TemplateKWLoc = Loc; + } + SourceLocation getLAngleLoc() const { return getLocalData()->LAngleLoc; } @@ -1271,13 +1288,17 @@ public: } SourceRange getLocalSourceRange() const { - return SourceRange(getTemplateNameLoc(), getRAngleLoc()); + if (getTemplateKeywordLoc().isValid()) + return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); + else + return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setTemplateKeywordLoc(Loc); + setTemplateNameLoc(Loc); setLAngleLoc(Loc); setRAngleLoc(Loc); - setTemplateNameLoc(Loc); initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), getArgInfos(), Loc); } @@ -1475,10 +1496,8 @@ class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, }; struct ElaboratedLocInfo { - SourceLocation KeywordLoc; - - /// \brief Opaque data pointer used to reconstruct a nested-name-specifier - /// from + SourceLocation ElaboratedKWLoc; + /// \brief Data associated with the nested-name-specifier location. void *QualifierData; }; @@ -1487,31 +1506,32 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, ElaboratedType, ElaboratedLocInfo> { public: - SourceLocation getKeywordLoc() const { - return this->getLocalData()->KeywordLoc; + SourceLocation getElaboratedKeywordLoc() const { + return this->getLocalData()->ElaboratedKWLoc; } - void setKeywordLoc(SourceLocation Loc) { - this->getLocalData()->KeywordLoc = Loc; + void setElaboratedKeywordLoc(SourceLocation Loc) { + this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } - + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - assert(QualifierLoc.getNestedNameSpecifier() + assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceRange getLocalSourceRange() const { - if (getKeywordLoc().isValid()) + if (getElaboratedKeywordLoc().isValid()) if (getQualifierLoc()) - return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc()); + return SourceRange(getElaboratedKeywordLoc(), + getQualifierLoc().getEndLoc()); else - return SourceRange(getKeywordLoc()); + return SourceRange(getElaboratedKeywordLoc()); else return getQualifierLoc().getSourceRange(); } @@ -1537,9 +1557,6 @@ public: // type is some sort of TypeDeclTypeLoc. struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; - - /// \brief Data associated with the nested-name-specifier location. - void *QualifierData; }; class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, @@ -1547,25 +1564,25 @@ class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DependentNameType, DependentNameLocInfo> { public: - SourceLocation getKeywordLoc() const { - return this->getLocalData()->KeywordLoc; + SourceLocation getElaboratedKeywordLoc() const { + return this->getLocalData()->ElaboratedKWLoc; } - void setKeywordLoc(SourceLocation Loc) { - this->getLocalData()->KeywordLoc = Loc; + void setElaboratedKeywordLoc(SourceLocation Loc) { + this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } - + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { - assert(QualifierLoc.getNestedNameSpecifier() + assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } - + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -1574,8 +1591,8 @@ public: } SourceRange getLocalSourceRange() const { - if (getKeywordLoc().isValid()) - return SourceRange(getKeywordLoc(), getNameLoc()); + if (getElaboratedKeywordLoc().isValid()) + return SourceRange(getElaboratedKeywordLoc(), getNameLoc()); else return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); } @@ -1590,7 +1607,7 @@ public: }; struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { - SourceLocation KeywordLoc; + SourceLocation TemplateKWLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // followed by a TemplateArgumentLocInfo[] @@ -1602,41 +1619,48 @@ class DependentTemplateSpecializationTypeLoc : DependentTemplateSpecializationType, DependentTemplateSpecializationLocInfo> { public: - SourceLocation getKeywordLoc() const { - return this->getLocalData()->KeywordLoc; + SourceLocation getElaboratedKeywordLoc() const { + return this->getLocalData()->ElaboratedKWLoc; } - void setKeywordLoc(SourceLocation Loc) { - this->getLocalData()->KeywordLoc = Loc; + void setElaboratedKeywordLoc(SourceLocation Loc) { + this->getLocalData()->ElaboratedKWLoc = Loc; } NestedNameSpecifierLoc getQualifierLoc() const { if (!getLocalData()->QualifierData) return NestedNameSpecifierLoc(); - - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), getLocalData()->QualifierData); } - + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { if (!QualifierLoc) { - // Even if we have a nested-name-specifier in the dependent + // Even if we have a nested-name-specifier in the dependent // template specialization type, we won't record the nested-name-specifier // location information when this type-source location information is // part of a nested-name-specifier. getLocalData()->QualifierData = 0; return; } - - assert(QualifierLoc.getNestedNameSpecifier() + + assert(QualifierLoc.getNestedNameSpecifier() == getTypePtr()->getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } - SourceLocation getNameLoc() const { + SourceLocation getTemplateKeywordLoc() const { + return getLocalData()->TemplateKWLoc; + } + void setTemplateKeywordLoc(SourceLocation Loc) { + getLocalData()->TemplateKWLoc = Loc; + } + + SourceLocation getTemplateNameLoc() const { return this->getLocalData()->NameLoc; } - void setNameLoc(SourceLocation Loc) { + void setTemplateNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } @@ -1670,12 +1694,14 @@ public: } SourceRange getLocalSourceRange() const { - if (getKeywordLoc().isValid()) - return SourceRange(getKeywordLoc(), getRAngleLoc()); + if (getElaboratedKeywordLoc().isValid()) + return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc()); else if (getQualifierLoc()) return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); + else if (getTemplateKeywordLoc().isValid()) + return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); else - return SourceRange(getNameLoc(), getRAngleLoc()); + return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } void copy(DependentTemplateSpecializationTypeLoc Loc) { @@ -1702,7 +1728,7 @@ struct PackExpansionTypeLocInfo { }; class PackExpansionTypeLoc - : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, + : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, PackExpansionType, PackExpansionTypeLocInfo> { public: SourceLocation getEllipsisLoc() const { @@ -1736,7 +1762,7 @@ struct AtomicTypeLocInfo { class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc, AtomicType, AtomicTypeLocInfo> { -public: +public: TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h index 9eebc4b..242aa58 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h @@ -28,11 +28,11 @@ public: RetTy Visit(const Type *T) { // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { - default: llvm_unreachable("Unknown type class!"); #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type); #include "clang/AST/TypeNodes.def" } + llvm_unreachable("Unknown type class!"); } // If the implementation chooses not to implement a certain visit method, fall diff --git a/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h b/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h deleted file mode 100644 index 534d4d4..0000000 --- a/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the UsuallyTinyPtrVector class, which is a vector that -// optimizes the case where there is only one element. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H -#define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H - -#include <vector> - -namespace clang { - -/// \brief A vector class template that is optimized for storing a single -/// pointer element. -template<typename T> -class UsuallyTinyPtrVector { - /// \brief Storage for the vector. - /// - /// When the low bit is zero, this is a T *. When the - /// low bit is one, this is a std::vector<T *> *. - mutable uintptr_t Storage; - - typedef std::vector<T*> vector_type; - -public: - UsuallyTinyPtrVector() : Storage(0) { } - explicit UsuallyTinyPtrVector(T *Element) - : Storage(reinterpret_cast<uintptr_t>(Element)) { } - - bool empty() const { return !Storage; } - - typedef const T **iterator; - iterator begin() const; - iterator end() const; - size_t size() const; - - void push_back(T *Method); - void Destroy(); -}; - -template<typename T> -typename UsuallyTinyPtrVector<T>::iterator -UsuallyTinyPtrVector<T>::begin() const { - if ((Storage & 0x01) == 0) - return reinterpret_cast<iterator>(&Storage); - - vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); - return &Vec->front(); -} - -template<typename T> -typename UsuallyTinyPtrVector<T>::iterator -UsuallyTinyPtrVector<T>::end() const { - if ((Storage & 0x01) == 0) { - if (Storage == 0) - return reinterpret_cast<iterator>(&Storage); - - return reinterpret_cast<iterator>(&Storage) + 1; - } - - vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); - return &Vec->front() + Vec->size(); -} - -template<typename T> -size_t UsuallyTinyPtrVector<T>::size() const { - if ((Storage & 0x01) == 0) - return (Storage == 0) ? 0 : 1; - - vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); - return Vec->size(); -} - -template<typename T> -void UsuallyTinyPtrVector<T>::push_back(T *Element) { - if (Storage == 0) { - // 0 -> 1 element. - Storage = reinterpret_cast<uintptr_t>(Element); - return; - } - - vector_type *Vec; - if ((Storage & 0x01) == 0) { - // 1 -> 2 elements. Allocate a new vector and push the element into that - // vector. - Vec = new vector_type; - Vec->push_back(reinterpret_cast<T *>(Storage)); - Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01; - } else - Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); - - // Add the new element to the vector. - Vec->push_back(Element); -} - -template<typename T> -void UsuallyTinyPtrVector<T>::Destroy() { - if (Storage & 0x01) - delete reinterpret_cast<vector_type *>(Storage & ~0x01); - - Storage = 0; -} - -} -#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h index 59bab03..2aa9a3d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h @@ -34,16 +34,16 @@ public: CK_OffsetToTop, CK_RTTI, CK_FunctionPointer, - + /// CK_CompleteDtorPointer - A pointer to the complete destructor. CK_CompleteDtorPointer, - + /// CK_DeletingDtorPointer - A pointer to the deleting destructor. CK_DeletingDtorPointer, - + /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer /// will end up never being called. Such vtable function pointers are - /// represented as a CK_UnusedFunctionPointer. + /// represented as a CK_UnusedFunctionPointer. CK_UnusedFunctionPointer }; @@ -60,34 +60,34 @@ public: static VTableComponent MakeOffsetToTop(CharUnits Offset) { return VTableComponent(CK_OffsetToTop, Offset); } - + static VTableComponent MakeRTTI(const CXXRecordDecl *RD) { return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD)); } static VTableComponent MakeFunction(const CXXMethodDecl *MD) { - assert(!isa<CXXDestructorDecl>(MD) && + assert(!isa<CXXDestructorDecl>(MD) && "Don't use MakeFunction with destructors!"); - return VTableComponent(CK_FunctionPointer, + return VTableComponent(CK_FunctionPointer, reinterpret_cast<uintptr_t>(MD)); } - + static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) { return VTableComponent(CK_CompleteDtorPointer, reinterpret_cast<uintptr_t>(DD)); } static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) { - return VTableComponent(CK_DeletingDtorPointer, + return VTableComponent(CK_DeletingDtorPointer, reinterpret_cast<uintptr_t>(DD)); } static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) { - assert(!isa<CXXDestructorDecl>(MD) && + assert(!isa<CXXDestructorDecl>(MD) && "Don't use MakeUnusedFunction with destructors!"); return VTableComponent(CK_UnusedFunctionPointer, - reinterpret_cast<uintptr_t>(MD)); + reinterpret_cast<uintptr_t>(MD)); } static VTableComponent getFromOpaqueInteger(uint64_t I) { @@ -101,88 +101,88 @@ public: CharUnits getVCallOffset() const { assert(getKind() == CK_VCallOffset && "Invalid component kind!"); - + return getOffset(); } CharUnits getVBaseOffset() const { assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); - + return getOffset(); } CharUnits getOffsetToTop() const { assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); - + return getOffset(); } - + const CXXRecordDecl *getRTTIDecl() const { assert(getKind() == CK_RTTI && "Invalid component kind!"); - + return reinterpret_cast<CXXRecordDecl *>(getPointer()); } - + const CXXMethodDecl *getFunctionDecl() const { assert(getKind() == CK_FunctionPointer); - + return reinterpret_cast<CXXMethodDecl *>(getPointer()); } const CXXDestructorDecl *getDestructorDecl() const { assert((getKind() == CK_CompleteDtorPointer || getKind() == CK_DeletingDtorPointer) && "Invalid component kind!"); - + return reinterpret_cast<CXXDestructorDecl *>(getPointer()); } const CXXMethodDecl *getUnusedFunctionDecl() const { assert(getKind() == CK_UnusedFunctionPointer); - + return reinterpret_cast<CXXMethodDecl *>(getPointer()); } - + private: VTableComponent(Kind ComponentKind, CharUnits Offset) { - assert((ComponentKind == CK_VCallOffset || + assert((ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); assert(Offset.getQuantity() <= ((1LL << 56) - 1) && "Offset is too big!"); - + Value = ((Offset.getQuantity() << 3) | ComponentKind); } VTableComponent(Kind ComponentKind, uintptr_t Ptr) { - assert((ComponentKind == CK_RTTI || + assert((ComponentKind == CK_RTTI || ComponentKind == CK_FunctionPointer || ComponentKind == CK_CompleteDtorPointer || ComponentKind == CK_DeletingDtorPointer || ComponentKind == CK_UnusedFunctionPointer) && "Invalid component kind!"); - + assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); - + Value = Ptr | ComponentKind; } - + CharUnits getOffset() const { assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || getKind() == CK_OffsetToTop) && "Invalid component kind!"); - + return CharUnits::fromQuantity(Value >> 3); } uintptr_t getPointer() const { - assert((getKind() == CK_RTTI || + assert((getKind() == CK_RTTI || getKind() == CK_FunctionPointer || getKind() == CK_CompleteDtorPointer || getKind() == CK_DeletingDtorPointer || getKind() == CK_UnusedFunctionPointer) && "Invalid component kind!"); - + return static_cast<uintptr_t>(Value & ~7ULL); } - + explicit VTableComponent(uint64_t Value) : Value(Value) { } @@ -210,7 +210,7 @@ private: /// VTableThunks - Contains thunks needed by vtables. uint64_t NumVTableThunks; VTableThunkTy *VTableThunks; - + /// Address points - Address points for all vtables. AddressPointsMapTy AddressPoints; @@ -265,10 +265,10 @@ class VTableContext { ASTContext &Context; public: - typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1> + typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1> VTableThunksTy; typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; - + private: /// MethodVTableIndices - Contains the index (relative to the vtable address /// point) where the function pointer for a virtual function is stored. @@ -279,22 +279,22 @@ private: VTableLayoutMapTy; VTableLayoutMapTy VTableLayouts; - /// NumVirtualFunctionPointers - Contains the number of virtual function + /// NumVirtualFunctionPointers - Contains the number of virtual function /// pointers in the vtable for a given record decl. llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers; typedef std::pair<const CXXRecordDecl *, const CXXRecordDecl *> ClassPairTy; - /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to + /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to /// the address point) in chars where the offsets for virtual bases of a class /// are stored. - typedef llvm::DenseMap<ClassPairTy, CharUnits> + typedef llvm::DenseMap<ClassPairTy, CharUnits> VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; - + /// Thunks - Contains all thunks that a given method decl will need. ThunksMapTy Thunks; @@ -312,7 +312,7 @@ public: const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { ComputeVTableRelatedInformation(RD); assert(VTableLayouts.count(RD) && "No layout for this record decl!"); - + return *VTableLayouts[RD]; } @@ -337,14 +337,14 @@ public: /// getNumVirtualFunctionPointers - Return the number of virtual function /// pointers in the vtable for a given record decl. uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); - + /// getMethodVTableIndex - Return the index (relative to the vtable address /// point) where the function pointer for the given virtual function is /// stored. uint64_t getMethodVTableIndex(GlobalDecl GD); /// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the - /// vtable address point) where the offset of the virtual base that contains + /// vtable address point) where the offset of the virtual base that contains /// the given base is stored, otherwise, if no virtual base contains the given /// class, return 0. Base must be a virtual base class or an unambigious /// base. diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h new file mode 100644 index 0000000..e9a431a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h @@ -0,0 +1,212 @@ +//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the dominators tree functionality for Clang CFGs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DOMINATORS_H +#define LLVM_CLANG_DOMINATORS_H + +#include "clang/Analysis/AnalysisContext.h" + +#include "llvm/Module.h" +#include "llvm/ADT/GraphTraits.h" +#include "clang/Analysis/CFG.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominatorInternals.h" + +namespace clang { + +class CFGBlock; +typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode; + +/// \brief Concrete subclass of DominatorTreeBase for Clang +/// This class implements the dominators tree functionality given a Clang CFG. +/// +class DominatorTree : public ManagedAnalysis { + virtual void anchor(); +public: + llvm::DominatorTreeBase<CFGBlock>* DT; + + DominatorTree() { + DT = new llvm::DominatorTreeBase<CFGBlock>(false); + } + + ~DominatorTree() { + delete DT; + } + + llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; } + + /// \brief This method returns the root CFGBlock of the dominators tree. + /// + inline CFGBlock *getRoot() const { + return DT->getRoot(); + } + + /// \brief This method returns the root DomTreeNode, which is the wrapper + /// for CFGBlock. + inline DomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + /// \brief This method compares two dominator trees. + /// The method returns false if the other dominator tree matches this + /// dominator tree, otherwise returns true. + /// + inline bool compare(DominatorTree &Other) const { + DomTreeNode *R = getRootNode(); + DomTreeNode *OtherR = Other.getRootNode(); + + if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) + return true; + + if (DT->compare(Other.getBase())) + return true; + + return false; + } + + /// \brief This method builds the dominator tree for a given CFG + /// The CFG information is passed via AnalysisDeclContext + /// + void buildDominatorTree(AnalysisDeclContext &AC) { + cfg = AC.getCFG(); + DT->recalculate(*cfg); + } + + /// \brief This method dumps immediate dominators for each block, + /// mainly used for debug purposes. + /// + void dump() { + llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; + for (CFG::const_iterator I = cfg->begin(), + E = cfg->end(); I != E; ++I) { + if(DT->getNode(*I)->getIDom()) + llvm::errs() << "(" << (*I)->getBlockID() + << "," + << DT->getNode(*I)->getIDom()->getBlock()->getBlockID() + << ")\n"; + else llvm::errs() << "(" << (*I)->getBlockID() + << "," << (*I)->getBlockID() << ")\n"; + } + } + + /// \brief This method tests if one CFGBlock dominates the other. + /// The method return true if A dominates B, false otherwise. + /// Note a block always dominates itself. + /// + inline bool dominates(const CFGBlock* A, const CFGBlock* B) const { + return DT->dominates(A, B); + } + + /// \brief This method tests if one CFGBlock properly dominates the other. + /// The method return true if A properly dominates B, false otherwise. + /// + bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const { + return DT->properlyDominates(A, B); + } + + /// \brief This method finds the nearest common dominator CFG block + /// for CFG block A and B. If there is no such block then return NULL. + /// + inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A, + const CFGBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + /// \brief This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + /// \brief This method tests if the given CFGBlock can be reachable from root. + /// Returns true if reachable, false otherwise. + /// + bool isReachableFromEntry(const CFGBlock *A) { + return DT->isReachableFromEntry(A); + } + + /// \brief This method releases the memory held by the dominator tree. + /// + virtual void releaseMemory() { + DT->releaseMemory(); + } + + /// \brief This method converts the dominator tree to human readable form. + /// + virtual void print(raw_ostream &OS, const llvm::Module* M= 0) const { + DT->print(OS); + } + +private: + CFG *cfg; +}; + +inline void WriteAsOperand(raw_ostream &OS, const CFGBlock *BB, + bool t) { + OS << "BB#" << BB->getBlockID(); +} + +} // end namespace clang + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// +namespace llvm { +template <> struct GraphTraits< ::clang::DomTreeNode* > { + typedef ::clang::DomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } + + typedef df_iterator< ::clang::DomTreeNode* > nodes_iterator; + + static nodes_iterator nodes_begin(::clang::DomTreeNode *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(::clang::DomTreeNode *N) { + return df_end(getEntryNode(N)); + } +}; + +template <> struct GraphTraits< ::clang::DominatorTree* > + : public GraphTraits< ::clang::DomTreeNode* > { + static NodeType *getEntryNode(::clang::DominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(::clang::DominatorTree *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(::clang::DominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h index a3f9c53..d4d8dc0 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h @@ -66,11 +66,14 @@ public: AsChar, // 'hh' AsShort, // 'h' AsLong, // 'l' - AsLongLong, // 'll', 'q' (BSD, deprecated) + AsLongLong, // 'll' + AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types) AsIntMax, // 'j' AsSizeT, // 'z' AsPtrDiff, // 't' AsLongDouble, // 'L' + AsAllocate, // for '%as', GNU extension to C90 scanf + AsMAllocate, // for '%ms', GNU extension to scanf AsWideChar = AsLong // for '%ls', only makes sense for printf }; @@ -104,7 +107,7 @@ private: const char *Position; Kind kind; }; - + class ConversionSpecifier { public: enum Kind { @@ -113,14 +116,14 @@ public: cArg, dArg, iArg, - IntArgBeg = cArg, IntArgEnd = iArg, - + IntArgBeg = cArg, IntArgEnd = iArg, + oArg, uArg, xArg, XArg, UIntArgBeg = oArg, UIntArgEnd = XArg, - + fArg, FArg, eArg, @@ -130,49 +133,49 @@ public: aArg, AArg, DoubleArgBeg = fArg, DoubleArgEnd = AArg, - + sArg, pArg, nArg, PercentArg, CArg, SArg, - + // ** Printf-specific ** - + // Objective-C specific specifiers. ObjCObjArg, // '@' ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, - + // FreeBSD specific specifiers bArg, DArg, rArg, - + // GlibC specific specifiers. PrintErrno, // 'm' - + PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno, - - // ** Scanf-specific ** + + // ** Scanf-specific ** ScanListArg, // '[' ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg }; - + ConversionSpecifier(bool isPrintf) : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {} - + ConversionSpecifier(bool isPrintf, const char *pos, Kind k) : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {} - + const char *getStart() const { return Position; } - + StringRef getCharacters() const { return StringRef(getStart(), getLength()); } - + bool consumesDataArgument() const { switch (kind) { case PrintErrno: @@ -183,15 +186,16 @@ public: return true; } } - + Kind getKind() const { return kind; } void setKind(Kind k) { kind = k; } unsigned getLength() const { return EndScanList ? EndScanList - Position : 1; } - + + bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } const char *toString() const; - + bool isPrintfKind() const { return IsPrintf; } protected: @@ -204,15 +208,18 @@ protected: class ArgTypeResult { public: enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, - CStrTy, WCStrTy, WIntTy }; + AnyCharTy, CStrTy, WCStrTy, WIntTy }; private: const Kind K; QualType T; - ArgTypeResult(bool) : K(InvalidTy) {} + const char *Name; + ArgTypeResult(bool) : K(InvalidTy), Name(0) {} public: - ArgTypeResult(Kind k = UnknownTy) : K(k) {} - ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} - ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} + ArgTypeResult(Kind k = UnknownTy) : K(k), Name(0) {} + ArgTypeResult(Kind k, const char *n) : K(k), Name(n) {} + ArgTypeResult(QualType t) : K(SpecificTy), T(t), Name(0) {} + ArgTypeResult(QualType t, const char *n) : K(SpecificTy), T(t), Name(n) {} + ArgTypeResult(CanQualType t) : K(SpecificTy), T(t), Name(0) {} static ArgTypeResult Invalid() { return ArgTypeResult(true); } @@ -227,6 +234,8 @@ public: bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } QualType getRepresentativeType(ASTContext &C) const; + + std::string getRepresentativeTypeName(ASTContext &C) const; }; class OptionalAmount { @@ -302,9 +311,9 @@ protected: LengthModifier LM; OptionalAmount FieldWidth; ConversionSpecifier CS; - /// Positional arguments, an IEEE extension: - /// IEEE Std 1003.1, 2004 Edition - /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html + /// Positional arguments, an IEEE extension: + /// IEEE Std 1003.1, 2004 Edition + /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html bool UsesPositionalArg; unsigned argIndex; public: @@ -342,8 +351,14 @@ public: } bool usesPositionalArg() const { return UsesPositionalArg; } - + bool hasValidLengthModifier() const; + + bool hasStandardLengthModifier() const; + + bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; + + bool hasStandardLengthConversionCombination() const; }; } // end analyze_format_string namespace @@ -353,7 +368,7 @@ public: namespace analyze_printf { -class PrintfConversionSpecifier : +class PrintfConversionSpecifier : public analyze_format_string::ConversionSpecifier { public: PrintfConversionSpecifier() @@ -364,9 +379,8 @@ public: bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; } - bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } - bool isDoubleArg() const { return kind >= DoubleArgBeg && - kind <= DoubleArgBeg; } + bool isDoubleArg() const { return kind >= DoubleArgBeg && + kind <= DoubleArgEnd; } unsigned getLength() const { // Conversion specifiers currently only are represented by // single characters, but we be flexible. @@ -443,7 +457,7 @@ public: const OptionalAmount &getPrecision() const { return Precision; } - + bool consumesDataArgument() const { return getConversionSpecifier().consumesDataArgument(); } @@ -453,9 +467,9 @@ public: /// will return null if the format specifier does not have /// a matching data argument or the matching argument matches /// more than one type. - ArgTypeResult getArgType(ASTContext &Ctx) const; + ArgTypeResult getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; - const OptionalFlag &hasThousandsGrouping() const { + const OptionalFlag &hasThousandsGrouping() const { return HasThousandsGrouping; } const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } @@ -465,14 +479,15 @@ public: const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } bool usesPositionalArg() const { return UsesPositionalArg; } - /// Changes the specifier and length according to a QualType, retaining any - /// flags or options. Returns true on success, or false when a conversion - /// was not successful. - bool fixType(QualType QT); + /// Changes the specifier and length according to a QualType, retaining any + /// flags or options. Returns true on success, or false when a conversion + /// was not successful. + bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, + bool IsObjCLiteral); void toString(raw_ostream &os) const; - // Validation methods - to check if any element results in undefined behavior + // Validation methods - to check if any element results in undefined behavior bool hasValidPlusPrefix() const; bool hasValidAlternativeForm() const; bool hasValidLeadingZeros() const; @@ -500,16 +515,41 @@ public: : ConversionSpecifier(false, pos, k) {} void setEndScanList(const char *pos) { EndScanList = pos; } - + static bool classof(const analyze_format_string::ConversionSpecifier *CS) { return !CS->isPrintfKind(); - } + } }; +using analyze_format_string::ArgTypeResult; using analyze_format_string::LengthModifier; using analyze_format_string::OptionalAmount; using analyze_format_string::OptionalFlag; +class ScanfArgTypeResult : public ArgTypeResult { +public: + enum Kind { UnknownTy, InvalidTy, CStrTy, WCStrTy, PtrToArgTypeResultTy }; +private: + Kind K; + ArgTypeResult A; + const char *Name; + QualType getRepresentativeType(ASTContext &C) const; +public: + ScanfArgTypeResult(Kind k = UnknownTy, const char* n = 0) : K(k), Name(n) {} + ScanfArgTypeResult(ArgTypeResult a, const char *n = 0) + : K(PtrToArgTypeResultTy), A(a), Name(n) { + assert(A.isValid()); + } + + static ScanfArgTypeResult Invalid() { return ScanfArgTypeResult(InvalidTy); } + + bool isValid() const { return K != InvalidTy; } + + bool matchesType(ASTContext& C, QualType argTy) const; + + std::string getRepresentativeTypeName(ASTContext& C) const; +}; + class ScanfSpecifier : public analyze_format_string::FormatSpecifier { OptionalFlag SuppressAssignment; // '*' public: @@ -533,11 +573,17 @@ public: const ScanfConversionSpecifier &getConversionSpecifier() const { return cast<ScanfConversionSpecifier>(CS); } - + bool consumesDataArgument() const { return CS.consumesDataArgument() && !SuppressAssignment; } + ScanfArgTypeResult getArgType(ASTContext &Ctx) const; + + bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx); + + void toString(raw_ostream &os) const; + static ScanfSpecifier Parse(const char *beg, const char *end); }; @@ -557,6 +603,8 @@ public: virtual void HandleNullChar(const char *nullCharacter) {} + virtual void HandlePosition(const char *startPos, unsigned posLen) {} + virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, PositionContext p) {} @@ -599,11 +647,10 @@ public: }; bool ParsePrintfString(FormatStringHandler &H, - const char *beg, const char *end, - bool FormatExtensions); + const char *beg, const char *end, const LangOptions &LO); bool ParseScanfString(FormatStringHandler &H, - const char *beg, const char *end); + const char *beg, const char *end, const LangOptions &LO); } // end analyze_format_string namespace } // end clang namespace diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h index 302ae1c..c9f39b4 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h @@ -52,7 +52,9 @@ public: friend class LiveVariables; }; - struct Observer { + class Observer { + virtual void anchor(); + public: virtual ~Observer() {} /// A callback invoked right before invoking the @@ -70,7 +72,7 @@ public: virtual ~LiveVariables(); /// Compute the liveness information for a given CFG. - static LiveVariables *computeLiveness(AnalysisContext &analysisContext, + static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign); /// Return true if a variable is live at the end of a @@ -93,7 +95,7 @@ public: void runOnAllBlocks(Observer &obs); - static LiveVariables *create(AnalysisContext &analysisContext) { + static LiveVariables *create(AnalysisDeclContext &analysisContext) { return computeLiveness(analysisContext, true); } @@ -106,7 +108,7 @@ private: class RelaxedLiveVariables : public LiveVariables { public: - static LiveVariables *create(AnalysisContext &analysisContext) { + static LiveVariables *create(AnalysisDeclContext &analysisContext) { return computeLiveness(analysisContext, false); } diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h new file mode 100644 index 0000000..4e3244e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -0,0 +1,111 @@ +//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements post order view of the blocks in a CFG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_POSTORDER_CFGVIEW +#define LLVM_CLANG_POSTORDER_CFGVIEW + +#include <vector> +//#include <algorithm> + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/BitVector.h" + +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" + +namespace clang { + +class PostOrderCFGView : public ManagedAnalysis { + virtual void anchor(); +public: + /// \brief Implements a set of CFGBlocks using a BitVector. + /// + /// This class contains a minimal interface, primarily dictated by the SetType + /// template parameter of the llvm::po_iterator template, as used with + /// external storage. We also use this set to keep track of which CFGBlocks we + /// visit during the analysis. + class CFGBlockSet { + llvm::BitVector VisitedBlockIDs; + public: + // po_iterator requires this iterator, but the only interface needed is the + // value_type typedef. + struct iterator { typedef const CFGBlock *value_type; }; + + CFGBlockSet() {} + CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {} + + /// \brief Set the bit associated with a particular CFGBlock. + /// This is the important method for the SetType template parameter. + bool insert(const CFGBlock *Block) { + // Note that insert() is called by po_iterator, which doesn't check to + // make sure that Block is non-null. Moreover, the CFGBlock iterator will + // occasionally hand out null pointers for pruned edges, so we catch those + // here. + if (Block == 0) + return false; // if an edge is trivially false. + if (VisitedBlockIDs.test(Block->getBlockID())) + return false; + VisitedBlockIDs.set(Block->getBlockID()); + return true; + } + + /// \brief Check if the bit for a CFGBlock has been already set. + /// This method is for tracking visited blocks in the main threadsafety + /// loop. Block must not be null. + bool alreadySet(const CFGBlock *Block) { + return VisitedBlockIDs.test(Block->getBlockID()); + } + }; + +private: + typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator; + std::vector<const CFGBlock*> Blocks; + + typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy; + BlockOrderTy BlockOrder; + +public: + typedef std::vector<const CFGBlock*>::reverse_iterator iterator; + + PostOrderCFGView(const CFG *cfg); + + iterator begin() { return Blocks.rbegin(); } + iterator end() { return Blocks.rend(); } + + bool empty() { return begin() == end(); } + + struct BlockOrderCompare; + friend struct BlockOrderCompare; + + struct BlockOrderCompare { + const PostOrderCFGView &POV; + public: + BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {} + bool operator()(const CFGBlock *b1, const CFGBlock *b2) const; + }; + + BlockOrderCompare getComparator() const { + return BlockOrderCompare(*this); + } + + // Used by AnalyisContext to construct this object. + static const void *getTag(); + + static PostOrderCFGView *create(AnalysisDeclContext &analysisContext); +}; + +} // end clang namespace + +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h index 6cf7fa4..30c5b2d 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -25,7 +25,7 @@ namespace llvm { } namespace clang { - class AnalysisContext; + class AnalysisDeclContext; class CFGBlock; } @@ -37,6 +37,7 @@ namespace clang { namespace reachable_code { class Callback { + virtual void anchor(); public: virtual ~Callback() {} virtual void HandleUnreachable(SourceLocation L, SourceRange R1, @@ -48,7 +49,7 @@ public: unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable); -void FindUnreachableCode(AnalysisContext &AC, Callback &CB); +void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB); }} // end namespace clang::reachable_code diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h index a325056..26e258d 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -67,7 +67,7 @@ enum LockErrorKind { class ThreadSafetyHandler { public: typedef llvm::StringRef Name; - virtual ~ThreadSafetyHandler() = 0; + virtual ~ThreadSafetyHandler(); /// Warn about lock expressions which fail to resolve to lockable objects. /// \param Loc -- the SourceLocation of the unresolved expression. @@ -93,9 +93,14 @@ public: /// 3. or when a mutex is locked but not unlocked inside a function. /// \param LockName -- A StringRef name for the lock expression, to be printed /// in the error message. - /// \param Loc -- The location of the lock expression where the mutex is locked + /// \param LocLocked -- The location of the lock expression where the mutex is + /// locked + /// \param LocEndOfScope -- The location of the end of the scope where the + /// mutex is no longer held /// \param LEK -- which of the three above cases we should warn for - virtual void handleMutexHeldEndOfScope(Name LockName, SourceLocation Loc, + virtual void handleMutexHeldEndOfScope(Name LockName, + SourceLocation LocLocked, + SourceLocation LocEndOfScope, LockErrorKind LEK){} /// Warn when a mutex is held exclusively and shared at the same point. For @@ -143,7 +148,8 @@ public: /// We traverse the blocks in the CFG, compute the set of mutexes that are held /// at the end of each block, and issue warnings for thread safety violations. /// Each block in the CFG is traversed exactly once. -void runThreadSafetyAnalysis(AnalysisContext &AC, ThreadSafetyHandler &Handler); +void runThreadSafetyAnalysis(AnalysisDeclContext &AC, + ThreadSafetyHandler &Handler); /// \brief Helper function that returns a LockKind required for the given level /// of access. diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h index e2e4f35..4ee6698 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h @@ -1,4 +1,4 @@ -//= UninitializedValues.h - Finding uses of uninitialized values --*- C++ -*-==// +//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -17,12 +17,12 @@ namespace clang { -class AnalysisContext; -class CFG; +class AnalysisDeclContext; +class CFG; class DeclContext; class Expr; class VarDecl; - + class UninitVariablesHandler { public: UninitVariablesHandler() {} @@ -32,7 +32,7 @@ public: virtual void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, bool isAlwaysUninit) {} - + /// Called when the uninitialized variable analysis detects the /// idiom 'int x = x'. All other uses of 'x' within the initializer /// are handled by handleUseOfUninitVariable. @@ -45,7 +45,7 @@ struct UninitVariablesAnalysisStats { }; void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, - AnalysisContext &ac, + AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h index 3d0e88a..6b6f8ef 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines AnalysisContext, a class that manages the analysis context -// data for path sensitive analysis. +// This file defines AnalysisDeclContext, a class that manages the analysis +// context data for path sensitive analysis. // //===----------------------------------------------------------------------===// @@ -38,17 +38,19 @@ class PseudoConstantAnalysis; class ImplicitParamDecl; class LocationContextManager; class StackFrameContext; - +class AnalysisDeclContextManager; +class LocationContext; + namespace idx { class TranslationUnit; } /// The base class of a hierarchy of objects representing analyses tied -/// to AnalysisContext. +/// to AnalysisDeclContext. class ManagedAnalysis { protected: ManagedAnalysis() {} public: virtual ~ManagedAnalysis(); - + // Subclasses need to implement: // // static const void *getTag(); @@ -56,47 +58,55 @@ public: // Which returns a fixed pointer address to distinguish classes of // analysis objects. They also need to implement: // - // static [Derived*] create(AnalysisContext &Ctx); + // static [Derived*] create(AnalysisDeclContext &Ctx); // - // which creates the analysis object given an AnalysisContext. + // which creates the analysis object given an AnalysisDeclContext. }; - -/// AnalysisContext contains the context data for the function or method under -/// analysis. -class AnalysisContext { + + +/// AnalysisDeclContext contains the context data for the function or method +/// under analysis. +class AnalysisDeclContext { + /// Backpoint to the AnalysisManager object that created this + /// AnalysisDeclContext. This may be null. + AnalysisDeclContextManager *Manager; + const Decl *D; // TranslationUnit is NULL if we don't have multiple translation units. idx::TranslationUnit *TU; - llvm::OwningPtr<CFG> cfg, completeCFG; - llvm::OwningPtr<CFGStmtMap> cfgStmtMap; + OwningPtr<CFG> cfg, completeCFG; + OwningPtr<CFGStmtMap> cfgStmtMap; CFG::BuildOptions cfgBuildOptions; CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; - + bool builtCFG, builtCompleteCFG; - llvm::OwningPtr<LiveVariables> liveness; - llvm::OwningPtr<LiveVariables> relaxedLiveness; - llvm::OwningPtr<ParentMap> PM; - llvm::OwningPtr<PseudoConstantAnalysis> PCA; - llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; + OwningPtr<LiveVariables> liveness; + OwningPtr<LiveVariables> relaxedLiveness; + OwningPtr<ParentMap> PM; + OwningPtr<PseudoConstantAnalysis> PCA; + OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; llvm::BumpPtrAllocator A; - // FIXME: remove. llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; void *ManagedAnalyses; public: - AnalysisContext(const Decl *d, idx::TranslationUnit *tu); + AnalysisDeclContext(AnalysisDeclContextManager *Mgr, + const Decl *D, + idx::TranslationUnit *TU); - AnalysisContext(const Decl *d, idx::TranslationUnit *tu, - const CFG::BuildOptions &buildOptions); + AnalysisDeclContext(AnalysisDeclContextManager *Mgr, + const Decl *D, + idx::TranslationUnit *TU, + const CFG::BuildOptions &BuildOptions); - ~AnalysisContext(); + ~AnalysisDeclContext(); ASTContext &getASTContext() { return D->getASTContext(); } const Decl *getDecl() const { return D; } @@ -111,12 +121,12 @@ public: const CFG::BuildOptions &getCFGBuildOptions() const { return cfgBuildOptions; } - + /// getAddEHEdges - Return true iff we are adding exceptional edges from /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. - bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } + bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } bool getUseUnoptimizedCFG() const { return !cfgBuildOptions.PruneTriviallyFalseEdges; } @@ -125,18 +135,18 @@ public: void registerForcedBlockExpression(const Stmt *stmt); const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); - + Stmt *getBody() const; CFG *getCFG(); - + CFGStmtMap *getCFGStmtMap(); CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); - + /// Return a version of the CFG without any edges pruned. CFG *getUnoptimizedCFG(); - void dumpCFG(); + void dumpCFG(bool ShowColors); /// \brief Returns true if we have built a CFG for this analysis context. /// Note that this doesn't correspond to whether or not a valid CFG exists, it @@ -152,9 +162,14 @@ public: getReferencedBlockVars(const BlockDecl *BD); /// Return the ImplicitParamDecl* associated with 'self' if this - /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. + /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise. const ImplicitParamDecl *getSelfDecl() const; - + + const StackFrameContext *getStackFrame(LocationContext const *Parent, + const Stmt *S, + const CFGBlock *Blk, + unsigned Idx); + /// Return the specified analysis object, lazily running the analysis if /// necessary. Return NULL if the analysis could not run. template <typename T> @@ -168,31 +183,8 @@ public: } private: ManagedAnalysis *&getAnalysisImpl(const void* tag); -}; - -class AnalysisContextManager { - typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; - ContextMap Contexts; - CFG::BuildOptions cfgBuildOptions; -public: - AnalysisContextManager(bool useUnoptimizedCFG = false, - bool addImplicitDtors = false, - bool addInitializers = false); - - ~AnalysisContextManager(); - AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); - - bool getUseUnoptimizedCFG() const { - return !cfgBuildOptions.PruneTriviallyFalseEdges; - } - - CFG::BuildOptions &getCFGBuildOptions() { - return cfgBuildOptions; - } - - /// Discard all previously created AnalysisContexts. - void clear(); + LocationContextManager &getLocationContextManager(); }; class LocationContext : public llvm::FoldingSetNode { @@ -202,13 +194,14 @@ public: private: ContextKind Kind; - // AnalysisContext can't be const since some methods may modify its member. - AnalysisContext *Ctx; + // AnalysisDeclContext can't be const since some methods may modify its + // member. + AnalysisDeclContext *Ctx; const LocationContext *Parent; protected: - LocationContext(ContextKind k, AnalysisContext *ctx, + LocationContext(ContextKind k, AnalysisDeclContext *ctx, const LocationContext *parent) : Kind(k), Ctx(ctx), Parent(parent) {} @@ -217,27 +210,27 @@ public: ContextKind getKind() const { return Kind; } - AnalysisContext *getAnalysisContext() const { return Ctx; } + AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } - idx::TranslationUnit *getTranslationUnit() const { - return Ctx->getTranslationUnit(); + idx::TranslationUnit *getTranslationUnit() const { + return Ctx->getTranslationUnit(); } const LocationContext *getParent() const { return Parent; } bool isParentOf(const LocationContext *LC) const; - const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } + const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); } - CFG *getCFG() const { return getAnalysisContext()->getCFG(); } + CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); } template <typename T> T *getAnalysis() const { - return getAnalysisContext()->getAnalysis<T>(); + return getAnalysisDeclContext()->getAnalysis<T>(); } ParentMap &getParentMap() const { - return getAnalysisContext()->getParentMap(); + return getAnalysisDeclContext()->getParentMap(); } const ImplicitParamDecl *getSelfDecl() const { @@ -255,7 +248,7 @@ public: public: static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, - AnalysisContext *ctx, + AnalysisDeclContext *ctx, const LocationContext *parent, const void *data); }; @@ -271,8 +264,8 @@ class StackFrameContext : public LocationContext { unsigned Index; friend class LocationContextManager; - StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s, const CFGBlock *blk, + StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent, + const Stmt *s, const CFGBlock *blk, unsigned idx) : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), Index(idx) {} @@ -288,7 +281,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx) { ProfileCommon(ID, StackFrame, ctx, parent, s); @@ -305,7 +298,7 @@ class ScopeContext : public LocationContext { const Stmt *Enter; friend class LocationContextManager; - ScopeContext(AnalysisContext *ctx, const LocationContext *parent, + ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(Scope, ctx, parent), Enter(s) {} @@ -314,7 +307,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s) { ProfileCommon(ID, Scope, ctx, parent, s); } @@ -331,7 +324,8 @@ class BlockInvocationContext : public LocationContext { friend class LocationContextManager; - BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + BlockInvocationContext(AnalysisDeclContext *ctx, + const LocationContext *parent, const BlockDecl *bd) : LocationContext(Block, ctx, parent), BD(bd) {} @@ -342,7 +336,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, const LocationContext *parent, const BlockDecl *bd) { ProfileCommon(ID, Block, ctx, parent, bd); } @@ -357,12 +351,12 @@ class LocationContextManager { public: ~LocationContextManager(); - const StackFrameContext *getStackFrame(AnalysisContext *ctx, + const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx); - const ScopeContext *getScope(AnalysisContext *ctx, + const ScopeContext *getScope(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s); @@ -370,10 +364,69 @@ public: void clear(); private: template <typename LOC, typename DATA> - const LOC *getLocationContext(AnalysisContext *ctx, + const LOC *getLocationContext(AnalysisDeclContext *ctx, const LocationContext *parent, const DATA *d); }; +class AnalysisDeclContextManager { + typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap; + + ContextMap Contexts; + LocationContextManager LocContexts; + CFG::BuildOptions cfgBuildOptions; + +public: + AnalysisDeclContextManager(bool useUnoptimizedCFG = false, + bool addImplicitDtors = false, + bool addInitializers = false); + + ~AnalysisDeclContextManager(); + + AnalysisDeclContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); + + bool getUseUnoptimizedCFG() const { + return !cfgBuildOptions.PruneTriviallyFalseEdges; + } + + CFG::BuildOptions &getCFGBuildOptions() { + return cfgBuildOptions; + } + + const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx, + LocationContext const *Parent, + const Stmt *S, + const CFGBlock *Blk, + unsigned Idx) { + return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx); + } + + // Get the top level stack frame. + const StackFrameContext *getStackFrame(Decl const *D, + idx::TranslationUnit *TU) { + return LocContexts.getStackFrame(getContext(D, TU), 0, 0, 0, 0); + } + + // Get a stack frame with parent. + StackFrameContext const *getStackFrame(const Decl *D, + LocationContext const *Parent, + const Stmt *S, + const CFGBlock *Blk, + unsigned Idx) { + return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); + } + + + /// Discard all previously created AnalysisDeclContexts. + void clear(); + +private: + friend class AnalysisDeclContext; + + LocationContextManager &getLocationContextManager() { + return LocContexts; + } +}; + } // end clang namespace #endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h index 16d31b4..d4e1f5f 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define ANALYSISSTART #include "clang/Basic/DiagnosticAnalysisKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h index f191c80..27b22b8 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h @@ -67,22 +67,22 @@ protected: CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0) : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} public: CFGElement() {} - Kind getKind() const { + Kind getKind() const { unsigned x = Data2.getInt(); x <<= 2; x |= Data1.getInt(); return (Kind) x; } - + bool isValid() const { return getKind() != Invalid; } operator bool() const { return isValid(); } - + template<class ElemTy> const ElemTy *getAs() const { if (llvm::isa<ElemTy>(this)) return static_cast<const ElemTy*>(this); @@ -96,7 +96,7 @@ class CFGStmt : public CFGElement { public: CFGStmt(Stmt *S) : CFGElement(Statement, S) {} - const Stmt *getStmt() const { + const Stmt *getStmt() const { return static_cast<const Stmt *>(Data1.getPointer()); } @@ -125,9 +125,9 @@ public: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) : CFGElement(kind, data1, data2) { - assert(kind >= DTOR_BEGIN && kind <= DTOR_END); + assert(kind >= DTOR_BEGIN && kind <= DTOR_END); } public: @@ -272,12 +272,12 @@ class CFGBlock { ImplTy Impl; public: ElementList(BumpVectorContext &C) : Impl(C, 4) {} - + typedef std::reverse_iterator<ImplTy::iterator> iterator; typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; typedef ImplTy::iterator reverse_iterator; - typedef ImplTy::const_iterator const_reverse_iterator; - + typedef ImplTy::const_iterator const_reverse_iterator; + void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, BumpVectorContext &C) { @@ -286,7 +286,7 @@ class CFGBlock { CFGElement front() const { return Impl.back(); } CFGElement back() const { return Impl.front(); } - + iterator begin() { return Impl.rbegin(); } iterator end() { return Impl.rend(); } const_iterator begin() const { return Impl.rbegin(); } @@ -300,7 +300,7 @@ class CFGBlock { assert(i < Impl.size()); return Impl[Impl.size() - 1 - i]; } - + size_t size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } }; @@ -344,10 +344,14 @@ class CFGBlock { /// storage if the memory usage of CFGBlock becomes an issue. unsigned HasNoReturnElement : 1; + /// Parent - The parent CFG that owns this CFGBlock. + CFG *Parent; + public: - explicit CFGBlock(unsigned blockid, BumpVectorContext &C) - : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), - BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false) {} + explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) + : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), + BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), + Parent(parent) {} ~CFGBlock() {} // Statement iterators @@ -489,16 +493,19 @@ public: unsigned getBlockID() const { return BlockID; } - void dump(const CFG *cfg, const LangOptions &LO) const; - void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const; + CFG *getParent() const { return Parent; } + + void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const; + void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO, + bool ShowColors) const; void printTerminator(raw_ostream &OS, const LangOptions &LO) const; - + void addSuccessor(CFGBlock *Block, BumpVectorContext &C) { if (Block) Block->Preds.push_back(this, C); Succs.push_back(Block, C); } - + void appendStmt(Stmt *statement, BumpVectorContext &C) { Elements.push_back(CFGStmt(statement), C); } @@ -515,7 +522,7 @@ public: void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) { Elements.push_back(CFGMemberDtor(FD), C); } - + void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) { Elements.push_back(CFGTemporaryDtor(E), C); } @@ -554,22 +561,22 @@ public: llvm::BitVector alwaysAddMask; public: typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; - ForcedBlkExprs **forcedBlkExprs; + ForcedBlkExprs **forcedBlkExprs; bool PruneTriviallyFalseEdges; bool AddEHEdges; bool AddInitializers; bool AddImplicitDtors; - + bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; } - + BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) { alwaysAddMask[stmtClass] = val; return *this; } - + BuildOptions &setAllAlwaysAdd() { alwaysAddMask.set(); return *this; @@ -583,6 +590,55 @@ public: ,AddImplicitDtors(false) {} }; + /// \brief Provides a custom implementation of the iterator class to have the + /// same interface as Function::iterator - iterator returns CFGBlock + /// (not a pointer to CFGBlock). + class graph_iterator { + public: + typedef const CFGBlock value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef BumpVector<CFGBlock*>::iterator ImplTy; + + graph_iterator(const ImplTy &i) : I(i) {} + + bool operator==(const graph_iterator &X) const { return I == X.I; } + bool operator!=(const graph_iterator &X) const { return I != X.I; } + + reference operator*() const { return **I; } + pointer operator->() const { return *I; } + operator CFGBlock* () { return *I; } + + graph_iterator &operator++() { ++I; return *this; } + graph_iterator &operator--() { --I; return *this; } + + private: + ImplTy I; + }; + + class const_graph_iterator { + public: + typedef const CFGBlock value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef BumpVector<CFGBlock*>::const_iterator ImplTy; + + const_graph_iterator(const ImplTy &i) : I(i) {} + + bool operator==(const const_graph_iterator &X) const { return I == X.I; } + bool operator!=(const const_graph_iterator &X) const { return I != X.I; } + + reference operator*() const { return **I; } + pointer operator->() const { return *I; } + operator CFGBlock* () const { return *I; } + + const_graph_iterator &operator++() { ++I; return *this; } + const_graph_iterator &operator--() { --I; return *this; } + + private: + ImplTy I; + }; + /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C, @@ -605,7 +661,7 @@ public: // Block Iterators //===--------------------------------------------------------------------===// - typedef BumpVector<CFGBlock*> CFGBlockListTy; + typedef BumpVector<CFGBlock*> CFGBlockListTy; typedef CFGBlockListTy::iterator iterator; typedef CFGBlockListTy::const_iterator const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; @@ -619,6 +675,15 @@ public: const_iterator begin() const { return Blocks.begin(); } const_iterator end() const { return Blocks.end(); } + graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); } + graph_iterator nodes_end() { return graph_iterator(Blocks.end()); } + const_graph_iterator nodes_begin() const { + return const_graph_iterator(Blocks.begin()); + } + const_graph_iterator nodes_end() const { + return const_graph_iterator(Blocks.end()); + } + reverse_iterator rbegin() { return Blocks.rbegin(); } reverse_iterator rend() { return Blocks.rend(); } const_reverse_iterator rbegin() const { return Blocks.rbegin(); } @@ -631,7 +696,7 @@ public: CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } - + typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator; try_block_iterator try_blocks_begin() const { return TryDispatchBlocks.begin(); @@ -639,7 +704,7 @@ public: try_block_iterator try_blocks_end() const { return TryDispatchBlocks.end(); } - + void addTryDispatchBlock(const CFGBlock *block) { TryDispatchBlocks.push_back(block); } @@ -681,13 +746,18 @@ public: /// start at 0). unsigned getNumBlockIDs() const { return NumBlockIDs; } + /// size - Return the total number of CFGBlocks within the CFG + /// This is simply a renaming of the getNumBlockIDs(). This is necessary + /// because the dominator implementation needs such an interface. + unsigned size() const { return NumBlockIDs; } + //===--------------------------------------------------------------------===// // CFG Debugging: Pretty-Printing and Visualization. //===--------------------------------------------------------------------===// void viewCFG(const LangOptions &LO) const; - void print(raw_ostream &OS, const LangOptions &LO) const; - void dump(const LangOptions &LO) const; + void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const; + void dump(const LangOptions &LO, bool ShowColors) const; //===--------------------------------------------------------------------===// // Internal: constructors and data. @@ -701,7 +771,7 @@ public: llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); } - + BumpVectorContext &getBumpVectorContext() { return BlkBVC; } @@ -717,11 +787,11 @@ private: // It represents a map from Expr* to integers to record the set of // block-level expressions and their "statement number" in the CFG. void * BlkExprMap; - + BumpVectorContext BlkBVC; - + CFGBlockListTy Blocks; - + /// C++ 'try' statements are modeled with an indirect dispatch block. /// This is the collection of such blocks present in the CFG. std::vector<const CFGBlock *> TryDispatchBlocks; @@ -781,6 +851,20 @@ template <> struct GraphTraits< const ::clang::CFGBlock *> { { return N->succ_end(); } }; +template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > { + typedef ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse< ::clang::CFGBlock*> G) + { return G.Graph; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->pred_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->pred_end(); } +}; + template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { typedef const ::clang::CFGBlock NodeType; typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; @@ -800,37 +884,55 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { template <> struct GraphTraits< ::clang::CFG* > : public GraphTraits< ::clang::CFGBlock *> { - typedef ::clang::CFG::iterator nodes_iterator; + typedef ::clang::CFG::graph_iterator nodes_iterator; - static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); } - static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); } - static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); } + static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} + static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); } + static unsigned size(::clang::CFG* F) { return F->size(); } }; template <> struct GraphTraits<const ::clang::CFG* > : public GraphTraits<const ::clang::CFGBlock *> { - typedef ::clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_graph_iterator nodes_iterator; static NodeType *getEntryNode( const ::clang::CFG* F) { return &F->getEntry(); } static nodes_iterator nodes_begin( const ::clang::CFG* F) { - return F->begin(); + return F->nodes_begin(); } static nodes_iterator nodes_end( const ::clang::CFG* F) { - return F->end(); + return F->nodes_end(); + } + static unsigned size(const ::clang::CFG* F) { + return F->size(); } }; +template <> struct GraphTraits<Inverse< ::clang::CFG*> > + : public GraphTraits<Inverse< ::clang::CFGBlock*> > { + + typedef ::clang::CFG::graph_iterator nodes_iterator; + + static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); } + static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} + static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } +}; + template <> struct GraphTraits<Inverse<const ::clang::CFG*> > : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef ::clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_graph_iterator nodes_iterator; static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); } - static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();} - static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { + return F->nodes_begin(); + } + static nodes_iterator nodes_end(const ::clang::CFG* F) { + return F->nodes_end(); + } }; } // end llvm namespace #endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h new file mode 100644 index 0000000..9b68073 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h @@ -0,0 +1,257 @@ +//== CallGraph.h - AST-based Call graph ------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AST-based CallGraph. +// +// A call graph for functions whose definitions/bodies are available in the +// current translation unit. The graph has a "virtual" root node that contains +// edges to all externally available functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH +#define LLVM_CLANG_ANALYSIS_CALLGRAPH + +#include "clang/AST/DeclBase.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SetVector.h" + +namespace clang { +class CallGraphNode; + +/// \class The AST-based call graph. +/// +/// The call graph extends itself with the given declarations by implementing +/// the recursive AST visitor, which constructs the graph by visiting the given +/// declarations. +class CallGraph : public RecursiveASTVisitor<CallGraph> { + friend class CallGraphNode; + + typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy; + + /// FunctionMap owns all CallGraphNodes. + FunctionMapTy FunctionMap; + + /// This is a virtual root node that has edges to all the global functions - + /// 'main' or functions accessible from other translation units. + CallGraphNode *Root; + + /// The list of nodes that have no parent. These are unreachable from Root. + /// Declarations can get to this list due to impressions in the graph, for + /// example, we do not track functions whose addresses were taken. + llvm::SetVector<CallGraphNode *> ParentlessNodes; + +public: + CallGraph(); + ~CallGraph(); + + /// \brief Populate the call graph with the functions in the given + /// declaration. + /// + /// Recursively walks the declaration to find all the dependent Decls as well. + void addToCallGraph(Decl *D) { + TraverseDecl(D); + } + + /// \brief Determine if a declaration should be included in the graph. + static bool includeInGraph(const Decl *D); + + /// \brief Lookup the node for the given declaration. + CallGraphNode *getNode(const Decl *) const; + + /// \brief Lookup the node for the given declaration. If none found, insert + /// one into the graph. + CallGraphNode *getOrInsertNode(Decl *); + + /// Iterators through all the elements in the graph. Note, this gives + /// non-deterministic order. + typedef FunctionMapTy::iterator iterator; + typedef FunctionMapTy::const_iterator const_iterator; + iterator begin() { return FunctionMap.begin(); } + iterator end() { return FunctionMap.end(); } + const_iterator begin() const { return FunctionMap.begin(); } + const_iterator end() const { return FunctionMap.end(); } + + /// \brief Get the number of nodes in the graph. + unsigned size() const { return FunctionMap.size(); } + + /// \ brief Get the virtual root of the graph, all the functions available + /// externally are represented as callees of the node. + CallGraphNode *getRoot() const { return Root; } + + /// Iterators through all the nodes of the graph that have no parent. These + /// are the unreachable nodes, which are either unused or are due to us + /// failing to add a call edge due to the analysis imprecision. + typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator; + typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator; + nodes_iterator parentless_begin() { return ParentlessNodes.begin(); } + nodes_iterator parentless_end() { return ParentlessNodes.end(); } + const_nodes_iterator + parentless_begin() const { return ParentlessNodes.begin(); } + const_nodes_iterator + parentless_end() const { return ParentlessNodes.end(); } + + void print(raw_ostream &os) const; + void dump() const; + void viewGraph() const; + + /// Part of recursive declaration visitation. + bool VisitFunctionDecl(FunctionDecl *FD) { + // We skip function template definitions, as their semantics is + // only determined when they are instantiated. + if (includeInGraph(FD)) + // If this function has external linkage, anything could call it. + // Note, we are not precise here. For example, the function could have + // its address taken. + addNodeForDecl(FD, FD->isGlobal()); + return true; + } + + /// Part of recursive declaration visitation. + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + if (includeInGraph(MD)) + addNodeForDecl(MD, true); + return true; + } + +private: + /// \brief Add the given declaration to the call graph. + void addNodeForDecl(Decl *D, bool IsGlobal); + + /// \brief Allocate a new node in the graph. + CallGraphNode *allocateNewNode(Decl *); +}; + +class CallGraphNode { +public: + typedef CallGraphNode* CallRecord; + +private: + /// \brief The function/method declaration. + Decl *FD; + + /// \brief The list of functions called from this node. + // Small vector might be more efficient since we are only tracking functions + // whose definition is in the current TU. + llvm::SmallVector<CallRecord, 5> CalledFunctions; + +public: + CallGraphNode(Decl *D) : FD(D) {} + + typedef llvm::SmallVector<CallRecord, 5>::iterator iterator; + typedef llvm::SmallVector<CallRecord, 5>::const_iterator const_iterator; + + /// Iterators through all the callees/children of the node. + inline iterator begin() { return CalledFunctions.begin(); } + inline iterator end() { return CalledFunctions.end(); } + inline const_iterator begin() const { return CalledFunctions.begin(); } + inline const_iterator end() const { return CalledFunctions.end(); } + + inline bool empty() const {return CalledFunctions.empty(); } + inline unsigned size() const {return CalledFunctions.size(); } + + void addCallee(CallGraphNode *N, CallGraph *CG) { + CalledFunctions.push_back(N); + CG->ParentlessNodes.remove(N); + } + + Decl *getDecl() const { return FD; } + + StringRef getName() const; + + void print(raw_ostream &os) const; + void dump() const; +}; + +} // end clang namespace + +// Graph traits for iteration, viewing. +namespace llvm { +template <> struct GraphTraits<clang::CallGraphNode*> { + typedef clang::CallGraphNode NodeType; + typedef clang::CallGraphNode::CallRecord CallRecordTy; + typedef std::pointer_to_unary_function<CallRecordTy, + clang::CallGraphNode*> CGNDerefFun; + static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } + typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType; + static inline ChildIteratorType child_begin(NodeType *N) { + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); + } + static inline ChildIteratorType child_end (NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + static clang::CallGraphNode *CGNDeref(CallRecordTy P) { + return P; + } +}; + +template <> struct GraphTraits<const clang::CallGraphNode*> { + typedef const clang::CallGraphNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } + static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } +}; + +template <> struct GraphTraits<clang::CallGraph*> + : public GraphTraits<clang::CallGraphNode*> { + + static NodeType *getEntryNode(clang::CallGraph *CGN) { + return CGN->getRoot(); // Start at the external node! + } + typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy; + typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun; + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator; + + static nodes_iterator nodes_begin(clang::CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end (clang::CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + static clang::CallGraphNode &CGdereference(PairTy P) { + return *(P.second); + } + + static unsigned size(clang::CallGraph *CG) { + return CG->size(); + } +}; + +template <> struct GraphTraits<const clang::CallGraph*> : + public GraphTraits<const clang::CallGraphNode*> { + static NodeType *getEntryNode(const clang::CallGraph *CGN) { + return CGN->getRoot(); + } + typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy; + typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun; + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef mapped_iterator<clang::CallGraph::const_iterator, + DerefFun> nodes_iterator; + + static nodes_iterator nodes_begin(const clang::CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end(const clang::CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + static clang::CallGraphNode &CGdereference(PairTy P) { + return *(P.second); + } + + static unsigned size(const clang::CallGraph *CG) { + return CG->size(); + } +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h index fa8afcc..e6a2f13 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -14,25 +14,15 @@ #ifndef LLVM_CLANG_ANALYSIS_DS_COCOA #define LLVM_CLANG_ANALYSIS_DS_COCOA -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" namespace clang { class FunctionDecl; -class ObjCMethodDecl; class QualType; namespace ento { namespace cocoa { - - enum NamingConvention { NoConvention, CreateRule, InitRule }; - - NamingConvention deriveNamingConvention(Selector S, const ObjCMethodDecl *MD); - - static inline bool followsFundamentalRule(Selector S, - const ObjCMethodDecl *MD) { - return deriveNamingConvention(S, MD) == CreateRule; - } bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name = StringRef()); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h index 7ec4ecd..b2200c6 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h @@ -19,6 +19,7 @@ #include "clang/Analysis/CFG.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/StringRef.h" @@ -28,7 +29,7 @@ namespace clang { -class AnalysisContext; +class AnalysisDeclContext; class FunctionDecl; class LocationContext; class ProgramPointTag; @@ -51,44 +52,72 @@ public: CallEnterKind, CallExitKind, MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = CallExitKind }; + MaxPostStmtKind = CallExitKind, + EpsilonKind}; private: - std::pair<const void *, const void *> Data; - Kind K; + llvm::PointerIntPair<const void *, 2, unsigned> Data1; + llvm::PointerIntPair<const void *, 2, unsigned> Data2; // The LocationContext could be NULL to allow ProgramPoint to be used in // context insensitive analysis. - const LocationContext *L; + llvm::PointerIntPair<const LocationContext *, 2, unsigned> L; + const ProgramPointTag *Tag; ProgramPoint(); protected: - ProgramPoint(const void *P, Kind k, const LocationContext *l, + ProgramPoint(const void *P, + Kind k, + const LocationContext *l, const ProgramPointTag *tag = 0) - : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {} - - ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l, + : Data1(P, ((unsigned) k) & 0x3), + Data2(0, (((unsigned) k) >> 2) & 0x3), + L(l, (((unsigned) k) >> 4) & 0x3), + Tag(tag) { + assert(getKind() == k); + assert(getLocationContext() == l); + assert(getData1() == P); + } + + ProgramPoint(const void *P1, + const void *P2, + Kind k, + const LocationContext *l, const ProgramPointTag *tag = 0) - : Data(P1, P2), K(k), L(l), Tag(tag) {} + : Data1(P1, ((unsigned) k) & 0x3), + Data2(P2, (((unsigned) k) >> 2) & 0x3), + L(l, (((unsigned) k) >> 4) & 0x3), + Tag(tag) {} protected: - const void *getData1() const { return Data.first; } - const void *getData2() const { return Data.second; } + const void *getData1() const { return Data1.getPointer(); } + const void *getData2() const { return Data2.getPointer(); } + void setData2(const void *d) { Data2.setPointer(d); } public: /// Create a new ProgramPoint object that is the same as the original /// except for using the specified tag value. ProgramPoint withTag(const ProgramPointTag *tag) const { - return ProgramPoint(Data.first, Data.second, K, L, tag); + return ProgramPoint(getData1(), getData2(), getKind(), + getLocationContext(), tag); } - Kind getKind() const { return K; } + Kind getKind() const { + unsigned x = L.getInt(); + x <<= 2; + x |= Data2.getInt(); + x <<= 2; + x |= Data1.getInt(); + return (Kind) x; + } const ProgramPointTag *getTag() const { return Tag; } - const LocationContext *getLocationContext() const { return L; } + const LocationContext *getLocationContext() const { + return L.getPointer(); + } // For use with DenseMap. This hash is probably slow. unsigned getHashValue() const { @@ -100,25 +129,30 @@ public: static bool classof(const ProgramPoint*) { return true; } bool operator==(const ProgramPoint & RHS) const { - return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag; + return Data1 == Data1 && + Data2 == RHS.Data2 && + L == RHS.L && + Tag == RHS.Tag; } bool operator!=(const ProgramPoint &RHS) const { - return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag; + return Data1 != RHS.Data1 || + Data2 != RHS.Data2 || + L != RHS.L || + Tag != RHS.Tag; } void Profile(llvm::FoldingSetNodeID& ID) const { - ID.AddInteger((unsigned) K); - ID.AddPointer(Data.first); - ID.AddPointer(Data.second); - ID.AddPointer(L); + ID.AddInteger((unsigned) getKind()); + ID.AddPointer(getData1()); + ID.AddPointer(getData2()); + ID.AddPointer(getLocationContext()); ID.AddPointer(Tag); } static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag); - }; class BlockEntrance : public ProgramPoint { @@ -195,7 +229,7 @@ public: class PostStmt : public StmtPoint { protected: PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, - const ProgramPointTag *tag =0) + const ProgramPointTag *tag = 0) : StmtPoint(S, data, k, L, tag) {} public: @@ -270,15 +304,29 @@ public: } }; +/// \class Represents a program point after a store evaluation. class PostStore : public PostStmt { public: - PostStore(const Stmt *S, const LocationContext *L, + /// Construct the post store point. + /// \param Loc can be used to store the information about the location + /// used in the form it was uttered in the code. + PostStore(const Stmt *S, const LocationContext *L, const void *Loc, const ProgramPointTag *tag = 0) - : PostStmt(S, PostStoreKind, L, tag) {} + : PostStmt(S, PostStoreKind, L, tag) { + assert(getData2() == 0); + setData2(Loc); + } static bool classof(const ProgramPoint* Location) { return Location->getKind() == PostStoreKind; } + + /// \brief Returns the information about the location used in the store, + /// how it was uttered in the code. + const void *getLocationValue() const { + return getData2(); + } + }; class PostLValue : public PostStmt { @@ -365,6 +413,21 @@ public: } }; +/// This is a meta program point, which should be skipped by all the diagnostic +/// reasoning etc. +class EpsilonPoint : public ProgramPoint { +public: + EpsilonPoint(const LocationContext *L, const void *Data1, + const void *Data2 = 0, const ProgramPointTag *tag = 0) + : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {} + + const void *getData() const { return getData1(); } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == EpsilonKind; + } +}; + /// ProgramPoints can be "tagged" as representing points specific to a given /// analysis entity. Tags are abstract annotations, with an associated /// description and potentially other information. diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h deleted file mode 100644 index f720639..0000000 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h +++ /dev/null @@ -1,47 +0,0 @@ -//===-- SaveAndRestore.h - Utility -------------------------------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides utility classes that uses RAII to save and restore -// values. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_SAVERESTORE -#define LLVM_CLANG_ANALYSIS_SAVERESTORE - -namespace clang { - -// SaveAndRestore - A utility class that uses RAII to save and restore -// the value of a variable. -template<typename T> -struct SaveAndRestore { - SaveAndRestore(T& x) : X(x), old_value(x) {} - SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) { - X = new_value; - } - ~SaveAndRestore() { X = old_value; } - T get() { return old_value; } -private: - T& X; - T old_value; -}; - -// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old -// value of a variable is saved, and during the dstor the old value is -// or'ed with the new value. -struct SaveOr { - SaveOr(bool& x) : X(x), old_value(x) { x = false; } - ~SaveOr() { X |= old_value; } -private: - bool& X; - const bool old_value; -}; - -} -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index 5c5ec2d..97eb287 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -66,6 +66,7 @@ public: DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl? DISPATCH_CASE(CXXRecord) DISPATCH_CASE(Enum) + DISPATCH_CASE(Field) DISPATCH_CASE(UsingDirective) DISPATCH_CASE(Using) default: @@ -82,8 +83,8 @@ public: DEFAULT_DISPATCH(Typedef) DEFAULT_DISPATCH(Record) DEFAULT_DISPATCH(Enum) + DEFAULT_DISPATCH(Field) DEFAULT_DISPATCH(ObjCInterface) - DEFAULT_DISPATCH(ObjCClass) DEFAULT_DISPATCH(ObjCMethod) DEFAULT_DISPATCH(ObjCProtocol) DEFAULT_DISPATCH(ObjCCategory) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h new file mode 100644 index 0000000..7e77435 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h @@ -0,0 +1,39 @@ +//===--- AllDiagnostics.h - Aggregate Diagnostic headers --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file includes all the separate Diagnostic headers & some related +// helpers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H +#define LLVM_CLANG_ALL_DIAGNOSTICS_H + +#include "clang/AST/ASTDiagnostic.h" +#include "clang/Analysis/AnalysisDiagnostic.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Lex/LexDiagnostic.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Serialization/SerializationDiagnostic.h" + +namespace clang { +template <size_t SizeOfStr, typename FieldType> +class StringSizerHelper { + char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1]; +public: + enum { Size = SizeOfStr }; +}; +} // end namespace clang + +#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \ + fieldTy>::Size + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td index 2a4ba5c..e8e0f35 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td @@ -93,6 +93,10 @@ class Attr { list<string> Namespaces = []; // Set to true for attributes with arguments which require delayed parsing. bit LateParsed = 0; + // Set to true for attributes which must be instantiated within templates + bit TemplateDependent = 0; + // Set to true for attributes which have handler in Sema. + bit SemaHandler = 1; // Any additional text that should be included verbatim in the class. code AdditionalMembers = [{}]; } @@ -122,6 +126,7 @@ def Aligned : InheritableAttr { def AlignMac68k : InheritableAttr { let Spellings = []; + let SemaHandler = 0; } def AlwaysInline : InheritableAttr { @@ -140,13 +145,14 @@ def Annotate : InheritableParamAttr { def AsmLabel : InheritableAttr { let Spellings = []; let Args = [StringArgument<"Label">]; + let SemaHandler = 0; } def Availability : InheritableAttr { let Spellings = ["availability"]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, - BoolArgument<"unavailable">]; + BoolArgument<"unavailable">, StringArgument<"message">]; let AdditionalMembers = [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch<llvm::StringRef>(Platform) @@ -274,6 +280,7 @@ def FastCall : InheritableAttr { def Final : InheritableAttr { let Spellings = []; + let SemaHandler = 0; } def MsStruct : InheritableAttr { @@ -315,6 +322,7 @@ def Malloc : InheritableAttr { def MaxFieldAlignment : InheritableAttr { let Spellings = []; let Args = [UnsignedArgument<"Alignment">]; + let SemaHandler = 0; } def MayAlias : InheritableAttr { @@ -324,14 +332,17 @@ def MayAlias : InheritableAttr { def MSP430Interrupt : InheritableAttr { let Spellings = []; let Args = [UnsignedArgument<"Number">]; + let SemaHandler = 0; } def MBlazeInterruptHandler : InheritableAttr { let Spellings = []; + let SemaHandler = 0; } def MBlazeSaveVolatiles : InheritableAttr { let Spellings = []; + let SemaHandler = 0; } def Naked : InheritableAttr { @@ -441,12 +452,18 @@ def ObjCReturnsInnerPointer : Attr { let Subjects = [ObjCMethod]; } +def ObjCRootClass : Attr { + let Spellings = ["objc_root_class"]; + let Subjects = [ObjCInterface]; +} + def Overloadable : Attr { let Spellings = ["overloadable"]; } def Override : InheritableAttr { let Spellings = []; + let SemaHandler = 0; } def Ownership : InheritableAttr { @@ -522,6 +539,12 @@ def Unavailable : InheritableAttr { def ArcWeakrefUnavailable : InheritableAttr { let Spellings = ["objc_arc_weak_reference_unavailable"]; + let Subjects = [ObjCInterface]; +} + +def ObjCRequiresPropertyDefs : InheritableAttr { + let Spellings = ["objc_requires_property_definitions"]; + let Subjects = [ObjCInterface]; } def Unused : InheritableAttr { @@ -570,6 +593,10 @@ def X86ForceAlignArgPointer : InheritableAttr { let Spellings = []; } +// AddressSafety attribute (e.g. for AddressSanitizer) +def NoAddressSafetyAnalysis : InheritableAttr { + let Spellings = ["no_address_safety_analysis"]; +} // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) @@ -597,36 +624,42 @@ def GuardedBy : InheritableAttr { let Spellings = ["guarded_by"]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; + let TemplateDependent = 1; } def PtGuardedBy : InheritableAttr { let Spellings = ["pt_guarded_by"]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; + let TemplateDependent = 1; } def AcquiredAfter : InheritableAttr { let Spellings = ["acquired_after"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def AcquiredBefore : InheritableAttr { let Spellings = ["acquired_before"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def ExclusiveLockFunction : InheritableAttr { let Spellings = ["exclusive_lock_function"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def SharedLockFunction : InheritableAttr { let Spellings = ["shared_lock_function"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } // The first argument is an integer or boolean value specifying the return value @@ -635,6 +668,7 @@ def ExclusiveTrylockFunction : InheritableAttr { let Spellings = ["exclusive_trylock_function"]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } // The first argument is an integer or boolean value specifying the return value @@ -643,34 +677,40 @@ def SharedTrylockFunction : InheritableAttr { let Spellings = ["shared_trylock_function"]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def UnlockFunction : InheritableAttr { let Spellings = ["unlock_function"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def LockReturned : InheritableAttr { let Spellings = ["lock_returned"]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; + let TemplateDependent = 1; } def LocksExcluded : InheritableAttr { let Spellings = ["locks_excluded"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def ExclusiveLocksRequired : InheritableAttr { let Spellings = ["exclusive_locks_required"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } def SharedLocksRequired : InheritableAttr { let Spellings = ["shared_locks_required"]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; + let TemplateDependent = 1; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def index da5aadf..d1af218 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def @@ -108,6 +108,8 @@ BUILTIN(__builtin_huge_vall, "Ld", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_labs , "LiLi" , "Fnc") +BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") BUILTIN(__builtin_ldexp , "ddi" , "Fnc") BUILTIN(__builtin_ldexpf, "ffi" , "Fnc") BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc") @@ -363,10 +365,12 @@ BUILTIN(__builtin_signbitf, "if", "nc") BUILTIN(__builtin_signbitl, "iLd", "nc") // Builtins for arithmetic. +BUILTIN(__builtin_clzs , "iUs" , "nc") BUILTIN(__builtin_clz , "iUi" , "nc") BUILTIN(__builtin_clzl , "iULi" , "nc") BUILTIN(__builtin_clzll, "iULLi", "nc") // TODO: int clzimax(uintmax_t) +BUILTIN(__builtin_ctzs , "iUs" , "nc") BUILTIN(__builtin_ctz , "iUi" , "nc") BUILTIN(__builtin_ctzl , "iULi" , "nc") BUILTIN(__builtin_ctzll, "iULLi", "nc") @@ -448,12 +452,15 @@ BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins BUILTIN(__builtin_object_size, "zvC*i", "n") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") +BUILTIN(__builtin___memccpy_chk, "v*v*vC*iz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memset_chk, "v*v*izz", "nF") BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF") +BUILTIN(__builtin___strlcat_chk, "c*c*cC*zz", "nF") +BUILTIN(__builtin___strlcpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___stpncpy_chk, "c*c*cC*zz", "nF") @@ -587,18 +594,57 @@ BUILTIN(__sync_swap_4, "iiD*i.", "tn") BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "tn") -BUILTIN(__atomic_load, "v.", "t") -BUILTIN(__atomic_store, "v.", "t") -BUILTIN(__atomic_exchange, "v.", "t") -BUILTIN(__atomic_compare_exchange_strong, "v.", "t") -BUILTIN(__atomic_compare_exchange_weak, "v.", "t") -BUILTIN(__atomic_fetch_add, "v.", "t") -BUILTIN(__atomic_fetch_sub, "v.", "t") -BUILTIN(__atomic_fetch_and, "v.", "t") -BUILTIN(__atomic_fetch_or, "v.", "t") -BUILTIN(__atomic_fetch_xor, "v.", "t") +// Some of our atomics builtins are handled by AtomicExpr rather than +// as normal builtin CallExprs. This macro is used for such builtins. +#ifndef ATOMIC_BUILTIN +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS) +#endif + +// C11 _Atomic operations for <stdatomic.h>. +ATOMIC_BUILTIN(__c11_atomic_init, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_load, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_store, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_compare_exchange_strong, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_compare_exchange_weak, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_xor, "v.", "t") +BUILTIN(__c11_atomic_thread_fence, "vi", "n") +BUILTIN(__c11_atomic_signal_fence, "vi", "n") +BUILTIN(__c11_atomic_is_lock_free, "iz", "n") + +// GNU atomic builtins. +ATOMIC_BUILTIN(__atomic_load, "v.", "t") +ATOMIC_BUILTIN(__atomic_load_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_store, "v.", "t") +ATOMIC_BUILTIN(__atomic_store_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__atomic_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_compare_exchange, "v.", "t") +ATOMIC_BUILTIN(__atomic_compare_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_xor, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_nand, "v.", "t") +ATOMIC_BUILTIN(__atomic_add_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_sub_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_and_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_or_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_xor_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_nand_fetch, "v.", "t") +BUILTIN(__atomic_test_and_set, "bvD*i", "n") +BUILTIN(__atomic_clear, "vvD*i", "n") BUILTIN(__atomic_thread_fence, "vi", "n") BUILTIN(__atomic_signal_fence, "vi", "n") +BUILTIN(__atomic_always_lock_free, "izvCD*", "n") +BUILTIN(__atomic_is_lock_free, "izvCD*", "n") + +#undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. BUILTIN(__sync_synchronize, "v.", "n") @@ -629,9 +675,12 @@ LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES) // C99 string.h LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strncmp, "icC*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) @@ -655,7 +704,12 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES) -LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(scanf, "icC*R.", "fs:0:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(fscanf, "iP*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(sscanf, "icC*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) // C99 LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES) @@ -671,6 +725,8 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES) +LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES) +LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES) // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES) LIBBUILTIN(vfork, "i", "fj", "unistd.h", ALL_LANGUAGES) @@ -698,6 +754,8 @@ LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG) // long double objc_msgSend_fpret(id self, SEL op, ...) LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG) +// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) +LIBBUILTIN(objc_msgSend_fp2ret, "XLdGH.", "f", "objc/message.h", OBJC_LANG) // id objc_msgSend_stret (id, SEL, ...) LIBBUILTIN(objc_msgSend_stret, "GGH.", "f", "objc/message.h", OBJC_LANG) // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) @@ -712,34 +770,39 @@ LIBBUILTIN(objc_getMetaClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG) LIBBUILTIN(objc_enumerationMutation, "vG", "f", "objc/runtime.h", OBJC_LANG) // id objc_read_weak(id *location) -LIBBUILTIN(objc_read_weak, "GG*", "f", "/objc/objc-auto.h", OBJC_LANG) +LIBBUILTIN(objc_read_weak, "GG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_weak(id value, id *location) -LIBBUILTIN(objc_assign_weak, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG) +LIBBUILTIN(objc_assign_weak, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_ivar(id value, id dest, ptrdiff_t offset) -LIBBUILTIN(objc_assign_ivar, "GGGY", "f", "/objc/objc-auto.h", OBJC_LANG) +LIBBUILTIN(objc_assign_ivar, "GGGY", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_global(id val, id *dest) -LIBBUILTIN(objc_assign_global, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG) +LIBBUILTIN(objc_assign_global, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_strongCast(id val, id *dest -LIBBUILTIN(objc_assign_strongCast, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG) +LIBBUILTIN(objc_assign_strongCast, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_exception_extract(void *localExceptionData) -LIBBUILTIN(objc_exception_extract, "Gv*", "f", "/objc/objc-exception.h", OBJC_LANG) +LIBBUILTIN(objc_exception_extract, "Gv*", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_try_enter(void *localExceptionData) -LIBBUILTIN(objc_exception_try_enter, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG) +LIBBUILTIN(objc_exception_try_enter, "vv*", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_try_exit(void *localExceptionData) -LIBBUILTIN(objc_exception_try_exit, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG) +LIBBUILTIN(objc_exception_try_exit, "vv*", "f", "objc/objc-exception.h", OBJC_LANG) // int objc_exception_match(Class exceptionClass, id exception) -LIBBUILTIN(objc_exception_match, "iGG", "f", "/objc/objc-exception.h", OBJC_LANG) +LIBBUILTIN(objc_exception_match, "iGG", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_throw(id exception) -LIBBUILTIN(objc_exception_throw, "vG", "f", "/objc/objc-exception.h", OBJC_LANG) +LIBBUILTIN(objc_exception_throw, "vG", "f", "objc/objc-exception.h", OBJC_LANG) // int objc_sync_enter(id obj) -LIBBUILTIN(objc_sync_enter, "iG", "f", "/objc/objc-sync.h", OBJC_LANG) +LIBBUILTIN(objc_sync_enter, "iG", "f", "objc/objc-sync.h", OBJC_LANG) // int objc_sync_exit(id obj) -LIBBUILTIN(objc_sync_exit, "iG", "f", "/objc/objc-sync.h", OBJC_LANG) +LIBBUILTIN(objc_sync_exit, "iG", "f", "objc/objc-sync.h", OBJC_LANG) BUILTIN(__builtin_objc_memmove_collectable, "v*v*vC*z", "nF") +// void NSLog(NSString *fmt, ...) +LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) +// void NSLogv(NSString *fmt, va_list args) +LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) + // Builtin math library functions LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def new file mode 100644 index 0000000..334224f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def @@ -0,0 +1,689 @@ +//==--- BuiltinsHexagon.def - Hexagon Builtin function database --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the X86-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +BUILTIN(__builtin_HEXAGON_C2_cmpeq, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgt, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgtu, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpeqp, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgtp, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgtup, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_C2_bitsset, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_bitsclr, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpeqi, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgti, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgtui, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgei, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpgeui, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmplt, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpltu, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_bitsclri, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_and, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_or, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_xor, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_andn, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_not, "bi", "") +BUILTIN(__builtin_HEXAGON_C2_orn, "bii", "") +BUILTIN(__builtin_HEXAGON_C2_pxfer_map, "bi", "") +BUILTIN(__builtin_HEXAGON_C2_any8, "bi", "") +BUILTIN(__builtin_HEXAGON_C2_all8, "bi", "") +BUILTIN(__builtin_HEXAGON_C2_vitpack, "iii", "") +BUILTIN(__builtin_HEXAGON_C2_mux, "iiii", "") +BUILTIN(__builtin_HEXAGON_C2_muxii, "iiii", "") +BUILTIN(__builtin_HEXAGON_C2_muxir, "iiii", "") +BUILTIN(__builtin_HEXAGON_C2_muxri, "iiii", "") +BUILTIN(__builtin_HEXAGON_C2_vmux, "LLiiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_C2_mask, "LLii", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpbeq, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpheq, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmphgt, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmphgtu, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpweq, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpwgt, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu, "bLLiLLi", "") +BUILTIN(__builtin_HEXAGON_C2_tfrpr, "ii", "") +BUILTIN(__builtin_HEXAGON_C2_tfrrp, "bi", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpysmi, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_macsip, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_macsin, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0, "ULLiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_mpy_up, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyu_up, "Uiii", "") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyi, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mpyui, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_maci, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_acci, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_accii, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_nacci, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_naccii, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_subacc, "iiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vmac2es, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrmac_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0, "iLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1, "iLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_cmacs_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmacs_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpys_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpys_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cnacs_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cnacs_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp, "iLLii", "") +BUILTIN(__builtin_HEXAGON_M2_mmacls_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacls_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmachs_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmachs_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1, "iii", "") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_cmaci_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmacr_s0, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0, "LLiii", "") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vcrotate, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_A2_add, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_sub, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addsat, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subsat, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addi, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_aslh, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_asrh, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_addp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_addpsat, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_addsp, "LLiiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_subp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_neg, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_negsat, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_abs, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_abssat, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_vconj, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_negp, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_absp, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_max, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_maxu, "Uiii", "") +BUILTIN(__builtin_HEXAGON_A2_min, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_minu, "Uiii", "") +BUILTIN(__builtin_HEXAGON_A2_maxp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_maxup, "ULLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_minp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_minup, "ULLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_tfr, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_tfrsi, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_tfrp, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_tfrpi, "LLii", "") +BUILTIN(__builtin_HEXAGON_A2_zxtb, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_sxtb, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_zxth, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_sxth, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_combinew, "LLiii", "") +BUILTIN(__builtin_HEXAGON_A2_combineii, "LLiii", "") +BUILTIN(__builtin_HEXAGON_A2_combine_hh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_combine_hl, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_combine_lh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_combine_ll, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_tfril, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_tfrih, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_and, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_or, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_xor, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_not, "ii", "") +BUILTIN(__builtin_HEXAGON_M2_xor_xacc, "iiii", "") +BUILTIN(__builtin_HEXAGON_A2_subri, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_andir, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_orir, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_andp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_orp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_xorp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_notp, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_sxtw, "LLii", "") +BUILTIN(__builtin_HEXAGON_A2_sat, "iLLi", "") +BUILTIN(__builtin_HEXAGON_A2_sath, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_satuh, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_satub, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_satb, "ii", "") +BUILTIN(__builtin_HEXAGON_A2_vaddub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vaddubs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vaddh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vaddhs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vadduhs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vaddw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vaddws, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_svavgh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svavghs, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svnavgh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svaddh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svaddhs, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svadduhs, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svsubh, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svsubhs, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_svsubuhs, "iii", "") +BUILTIN(__builtin_HEXAGON_A2_vraddub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vraddub_acc, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vradduh, "iLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsububs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubhs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubuhs, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vsubws, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vabsh, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vabshsat, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vabsw, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vabswsat, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vabsdiffw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_M2_vabsdiffh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vrsadub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavguh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavgh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavgw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgwr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavgwr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgwcr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavgwcr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavghcr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavghcr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavguw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavguwr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavgubr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavguhr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vavghr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vnavghr, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vminh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vmaxh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vminub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vmaxub, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vminuh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vmaxuh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vminw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vmaxw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vminuw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A2_vmaxuw, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_addasl_rrri, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_valignib, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_valignrb, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_vspliceib, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_vsplicerb, "LLiLLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_vsplatrh, "LLii", "") +BUILTIN(__builtin_HEXAGON_S2_vsplatrb, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_insert, "iiiii", "") +BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax, "iiiii", "") +BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax, "iiiii", "") +BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax, "iiiii", "") +BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax, "iiiii", "") +BUILTIN(__builtin_HEXAGON_S2_extractu, "iiii", "") +BUILTIN(__builtin_HEXAGON_S2_insertp, "LLiLLiLLiii", "") +BUILTIN(__builtin_HEXAGON_S2_extractup, "LLiLLiii", "") +BUILTIN(__builtin_HEXAGON_S2_insert_rp, "iiiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_extractu_rp, "iiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_insertp_rp, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_extractup_rp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_tstbit_i, "bii", "") +BUILTIN(__builtin_HEXAGON_S2_setbit_i, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_togglebit_i, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_clrbit_i, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_tstbit_r, "bii", "") +BUILTIN(__builtin_HEXAGON_S2_setbit_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_togglebit_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_clrbit_r, "iii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun, "iLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun, "iLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_i_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asr_r_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_asl_r_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw, "LLiLLii", "") +BUILTIN(__builtin_HEXAGON_S2_vrndpackwh, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsxtbh, "LLii", "") +BUILTIN(__builtin_HEXAGON_S2_vzxtbh, "LLii", "") +BUILTIN(__builtin_HEXAGON_S2_vsathub, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_svsathub, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_svsathb, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_vsathb, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vtrunohb, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vtrunewh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vtrunowh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vtrunehb, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsxthw, "LLii", "") +BUILTIN(__builtin_HEXAGON_S2_vzxthw, "LLii", "") +BUILTIN(__builtin_HEXAGON_S2_vsatwh, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsatwuh, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_packhl, "LLiii", "") +BUILTIN(__builtin_HEXAGON_A2_swiz, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_shuffob, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_shuffeb, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_shuffoh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_shuffeh, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_parityp, "iLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_lfsp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_clbnorm, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_clb, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_cl0, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_cl1, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_clbp, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_cl0p, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_cl1p, "iLLi", "") +BUILTIN(__builtin_HEXAGON_S2_brev, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_ct0, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_ct1, "ii", "") +BUILTIN(__builtin_HEXAGON_S2_interleave, "LLiLLi", "") +BUILTIN(__builtin_HEXAGON_S2_deinterleave, "LLiLLi", "") + +BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "") + +BUILTIN(__builtin_M2_vrcmpys_s1, "LLiLLii", "") +BUILTIN(__builtin_M2_vrcmpys_acc_s1, "LLiLLiLLii", "") +BUILTIN(__builtin_M2_vrcmpys_s1rp, "iLLii", "") + +BUILTIN(__builtin_M2_vradduh, "iLLiLLi", "") +BUILTIN(__builtin_A2_addsp, "LLiiLLi", "") +BUILTIN(__builtin_A2_addpsat, "LLiLLiLLi", "") + +BUILTIN(__builtin_A2_maxp, "LLiLLiLLi", "") +BUILTIN(__builtin_A2_maxup, "LLiLLiLLi", "") + +BUILTIN(__builtin_HEXAGON_A4_orn, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_andn, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_ornp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A4_andnp, "LLiLLiLLi", "") +BUILTIN(__builtin_HEXAGON_A4_combineir, "LLiii", "") +BUILTIN(__builtin_HEXAGON_A4_combineri, "LLiii", "") +BUILTIN(__builtin_HEXAGON_C4_cmpneqi, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_cmpneq, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_cmpltei, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_cmplte, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_cmplteui, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_cmplteu, "bii", "") +BUILTIN(__builtin_HEXAGON_A4_rcmpneq, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_rcmpneqi, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_rcmpeq, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_rcmpeqi, "iii", "") +BUILTIN(__builtin_HEXAGON_C4_fastcorner9, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not, "bii", "") +BUILTIN(__builtin_HEXAGON_C4_and_andn, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_and_and, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_and_orn, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_and_or, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_or_andn, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_or_and, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_or_orn, "biii", "") +BUILTIN(__builtin_HEXAGON_C4_or_or, "biii", "") +BUILTIN(__builtin_HEXAGON_S4_addaddi, "iiii", "") +BUILTIN(__builtin_HEXAGON_S4_subaddi, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_xor_xacc, "LLiLLiLLiLLi", "") + +BUILTIN(__builtin_HEXAGON_M4_and_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_and_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_and_xor, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_and_andn, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_xor_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_xor_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_xor_andn, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_or_and, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_or_or, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_or_xor, "iiii", "") +BUILTIN(__builtin_HEXAGON_M4_or_andn, "iiii", "") +BUILTIN(__builtin_HEXAGON_S4_or_andix, "iiii", "") +BUILTIN(__builtin_HEXAGON_S4_or_andi, "iiii", "") +BUILTIN(__builtin_HEXAGON_S4_or_ori, "iiii", "") + +BUILTIN(__builtin_HEXAGON_A4_modwrapu, "iii", "") + +BUILTIN(__builtin_HEXAGON_A4_cround_ri, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_cround_rr, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_round_ri, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_round_rr, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_round_ri_sat, "iii", "") +BUILTIN(__builtin_HEXAGON_A4_round_rr_sat, "iii", "") + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def index 6bd9014..f44aed6 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def @@ -42,8 +42,6 @@ BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc") BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc") -// GCC has pfrsqrtit1, even though this is not the name of the instruction. -BUILTIN(__builtin_ia32_pfrsqrtit1, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc") BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc") @@ -187,14 +185,14 @@ BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "") BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "") BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "") BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "") -BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fc", "") -BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fc", "") +BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "") +BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "") BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") -BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "") -BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "") +BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "") +BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "") BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "") @@ -210,19 +208,13 @@ BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "") BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_pcmpeqb128, "V16cV16cV16c", "") -BUILTIN(__builtin_ia32_pcmpeqw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_pcmpeqd128, "V4iV4iV4i", "") -BUILTIN(__builtin_ia32_pcmpgtb128, "V16cV16cV16c", "") -BUILTIN(__builtin_ia32_pcmpgtw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_pcmpgtd128, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "") BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "") BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_packsswb128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_packssdw128, "V4iV4iV4i", "") -BUILTIN(__builtin_ia32_packuswb128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "") +BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "") +BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "") BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "") @@ -236,7 +228,7 @@ BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "") -BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "") BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "") BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "") @@ -304,19 +296,19 @@ BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "") BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "") BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "") BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "") -BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "") BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") -BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") // FIXME: Correct type? +BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "") -BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8si", "") -BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2di", "") -BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "") +BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "") +BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "") BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "") BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "") @@ -353,28 +345,26 @@ BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "") BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "") BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "") BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "") -BUILTIN(__builtin_ia32_pcmpeqq, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16ci", "") +BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "") // SSE 4.2 -BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cc", "") -BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cc", "") -BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16cic", "") -BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16cic","") +BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "") +BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "") +BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "") +BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","") -BUILTIN(__builtin_ia32_pcmpistria128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpistric128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpistrio128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpistris128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpistriz128, "iV16ciV16cic","") - -BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16cic","") -BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16cic","") - -BUILTIN(__builtin_ia32_pcmpgtq, "V2LLiV2LLiV2LLi", "") +// FIXME: These builtins are horribly broken; reenable when PR11305 is fixed. +//BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","") +//BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","") +//BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","") +//BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","") +//BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","") +//BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","") +//BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","") +//BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciic","") +//BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","") +//BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","") BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "") BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "") @@ -387,7 +377,7 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") -BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "") +BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "") // AVX BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "") @@ -404,16 +394,16 @@ BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "") BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "") BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "") BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "") -BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "") -BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "") +BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "") +BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "") BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "") BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "") -BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "") +BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIi", "") BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "") BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "") -BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "") -BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "") -BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "") +BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "") +BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "") +BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "") BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "") BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "") BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "") @@ -422,22 +412,15 @@ BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "") BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "") BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "") BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "") -BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "") -BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "") -BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "") -BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "") -BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "") -BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "") -BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "") -BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "") -BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "") -BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "") +BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIc", "") +BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIc", "") +BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIc", "") BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "") BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "") BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "") BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "") -BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "") -BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "") +BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "") +BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "") BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "") BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "") BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "") @@ -462,11 +445,8 @@ BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "") BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "") BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "") BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "") -BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "") -BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "") BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "") BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "") -BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "") BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "") BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "") BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "") @@ -481,4 +461,173 @@ BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "") BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "") BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "") +// AVX2 +BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32ci", "") +BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "") +BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "") +BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "") +BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "") +BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "") +BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "") +BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "") +BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "") +BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "") +BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "") +BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "") +BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "") +BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "") +BUILTIN(__builtin_ia32_pmovsxbw256, "V16sV16c", "") +BUILTIN(__builtin_ia32_pmovsxbd256, "V8iV16c", "") +BUILTIN(__builtin_ia32_pmovsxbq256, "V4LLiV16c", "") +BUILTIN(__builtin_ia32_pmovsxwd256, "V8iV8s", "") +BUILTIN(__builtin_ia32_pmovsxwq256, "V4LLiV8s", "") +BUILTIN(__builtin_ia32_pmovsxdq256, "V4LLiV4i", "") +BUILTIN(__builtin_ia32_pmovzxbw256, "V16sV16c", "") +BUILTIN(__builtin_ia32_pmovzxbd256, "V8iV16c", "") +BUILTIN(__builtin_ia32_pmovzxbq256, "V4LLiV16c", "") +BUILTIN(__builtin_ia32_pmovzxwd256, "V8iV8s", "") +BUILTIN(__builtin_ia32_pmovzxwq256, "V4LLiV8s", "") +BUILTIN(__builtin_ia32_pmovzxdq256, "V4LLiV4i", "") +BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "") +BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "") +BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "") +BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "") +BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "") +BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_pslldqi256, "V4LLiV4LLiIi", "") +BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "") +BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "") +BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "") +BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "") +BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "") +BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "") +BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "") +BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "") +BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "") +BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "") +BUILTIN(__builtin_ia32_psrldqi256, "V4LLiV4LLiIi", "") +BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "") +BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "") +BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "") +BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "") +BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "") +BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "") +BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLi*", "") +BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "") +BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "") +BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "") +BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLiC*", "") +BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "") +BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "") +BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "") +BUILTIN(__builtin_ia32_pbroadcastw256, "V16sV8s", "") +BUILTIN(__builtin_ia32_pbroadcastd256, "V8iV4i", "") +BUILTIN(__builtin_ia32_pbroadcastq256, "V4LLiV2LLi", "") +BUILTIN(__builtin_ia32_pbroadcastb128, "V16cV16c", "") +BUILTIN(__builtin_ia32_pbroadcastw128, "V8sV8s", "") +BUILTIN(__builtin_ia32_pbroadcastd128, "V4iV4i", "") +BUILTIN(__builtin_ia32_pbroadcastq128, "V2LLiV2LLi", "") +BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_permdf256, "V4dV4dIc", "") +BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8f", "") +BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIc", "") +BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIc", "") +BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIc", "") +BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "") +BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "") +BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "") +BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "") +BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "") +BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "") +BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "") +BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "") +BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "") + +// BMI +BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "") +BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "") + +// BMI2 +BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "") +BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "") +BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "") +BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "") +BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "") +BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "") + +// FMA4 +BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfnmsubsd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmsubaddps, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "") +BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "") + #undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h index d928f9d..ec6b973 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h @@ -98,7 +98,7 @@ bit mask & shift operations. ------------------------------------------------------------------------ */ -typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned int UTF32; /* at least 32 bits */ typedef unsigned short UTF16; /* at least 16 bits */ typedef unsigned char UTF8; /* typically 8 bits */ typedef unsigned char Boolean; /* 0 or 1 */ @@ -131,15 +131,15 @@ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + #ifdef CLANG_NEEDS_THESE_ONE_DAY ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); @@ -151,9 +151,11 @@ ConversionResult ConvertUTF16toUTF32 ( ConversionResult ConvertUTF32toUTF16 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); -#endif Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); +#endif + +Boolean isLegalUTF8String(const UTF8 *source, const UTF8 *sourceEnd); #ifdef __cplusplus } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td index a37dc10..6f2bb35 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td @@ -66,8 +66,6 @@ def Named : Decl<1>; def ObjCCompatibleAlias : DDecl<Named>; def LinkageSpec : Decl, DeclContext; def ObjCPropertyImpl : Decl; -def ObjCForwardProtocol : Decl; -def ObjCClass : Decl; def FileScopeAsm : Decl; def AccessSpec : Decl; def Friend : Decl; @@ -75,3 +73,5 @@ def FriendTemplate : Decl; def StaticAssert : Decl; def Block : Decl, DeclContext; def ClassScopeFunctionSpecialization : Decl; +def Import : Decl; + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h index fefc44c..e157178 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h @@ -50,13 +50,19 @@ public: /// insertion hint. CharSourceRange RemoveRange; + /// \brief Code in the specific range that should be inserted in the insertion + /// location. + CharSourceRange InsertFromRange; + /// \brief The actual code to insert at the insertion location, as a /// string. std::string CodeToInsert; + bool BeforePreviousInsertions; + /// \brief Empty code modification hint, indicating that no code /// modification is known. - FixItHint() : RemoveRange() { } + FixItHint() : BeforePreviousInsertions(false) { } bool isNull() const { return !RemoveRange.isValid(); @@ -65,11 +71,26 @@ public: /// \brief Create a code modification hint that inserts the given /// code string at a specific location. static FixItHint CreateInsertion(SourceLocation InsertionLoc, - StringRef Code) { + StringRef Code, + bool BeforePreviousInsertions = false) { FixItHint Hint; Hint.RemoveRange = CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false); Hint.CodeToInsert = Code; + Hint.BeforePreviousInsertions = BeforePreviousInsertions; + return Hint; + } + + /// \brief Create a code modification hint that inserts the given + /// code from \arg FromRange at a specific location. + static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, + CharSourceRange FromRange, + bool BeforePreviousInsertions = false) { + FixItHint Hint; + Hint.RemoveRange = + CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false); + Hint.InsertFromRange = FromRange; + Hint.BeforePreviousInsertions = BeforePreviousInsertions; return Hint; } @@ -105,7 +126,7 @@ public: /// "report warnings as errors" and passes them off to the DiagnosticConsumer /// for reporting to the user. DiagnosticsEngine is tied to one translation unit /// and one SourceManager. -class DiagnosticsEngine : public llvm::RefCountedBase<DiagnosticsEngine> { +class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { public: /// Level - The level of the diagnostic, after it has been through mapping. enum Level { @@ -158,8 +179,10 @@ private: unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, // 0 -> no limit. + unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation + // backtrace stack, 0 -> no limit. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? - llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags; + IntrusiveRefCntPtr<DiagnosticIDs> Diags; DiagnosticConsumer *Client; bool OwnsDiagClient; SourceManager *SourceMgr; @@ -287,7 +310,7 @@ private: unsigned NumPrevArgs, SmallVectorImpl<char> &Output, void *Cookie, - SmallVectorImpl<intptr_t> &QualTypeVals); + ArrayRef<intptr_t> QualTypeVals); void *ArgToStringCookie; ArgToStringFnTy ArgToStringFn; @@ -304,12 +327,12 @@ private: public: explicit DiagnosticsEngine( - const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags, + const IntrusiveRefCntPtr<DiagnosticIDs> &Diags, DiagnosticConsumer *client = 0, bool ShouldOwnClient = true); ~DiagnosticsEngine(); - const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { + const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { return Diags; } @@ -363,13 +386,25 @@ public: void setTemplateBacktraceLimit(unsigned Limit) { TemplateBacktraceLimit = Limit; } - + /// \brief Retrieve the maximum number of template instantiation - /// nodes to emit along with a given diagnostic. + /// notes to emit along with a given diagnostic. unsigned getTemplateBacktraceLimit() const { return TemplateBacktraceLimit; } - + + /// \brief Specify the maximum number of constexpr evaluation + /// notes to emit along with a given diagnostic. + void setConstexprBacktraceLimit(unsigned Limit) { + ConstexprBacktraceLimit = Limit; + } + + /// \brief Retrieve the maximum number of constexpr evaluation + /// notes to emit along with a given diagnostic. + unsigned getConstexprBacktraceLimit() const { + return ConstexprBacktraceLimit; + } + /// setIgnoreAllWarnings - When set to true, any unmapped warnings are /// ignored. If this and WarningsAsErrors are both set, then this one wins. void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; } @@ -450,18 +485,32 @@ public: bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map, SourceLocation Loc = SourceLocation()); + /// \brief Set the warning-as-error flag for the given diagnostic. This + /// function always only operates on the current diagnostic state. + void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled); + /// \brief Set the warning-as-error flag for the given diagnostic group. This /// function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); + /// \brief Set the error-as-fatal flag for the given diagnostic. This function + /// always only operates on the current diagnostic state. + void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled); + /// \brief Set the error-as-fatal flag for the given diagnostic group. This /// function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); + /// \brief Add the specified mapping to all diagnostics. Mainly to be used + /// by -Wno-everything to disable all warnings but allow subsequent -W options + /// to enable specific warnings. + void setMappingToAllDiagnostics(diag::Mapping Map, + SourceLocation Loc = SourceLocation()); + bool hasErrorOccurred() const { return ErrorOccurred; } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } @@ -587,16 +636,22 @@ private: /// MaxArguments - The maximum number of arguments we can hold. We currently /// only support up to 10 arguments (%0-%9). A single diagnostic with more /// than that almost certainly has to be simplified anyway. - MaxArguments = 10 + MaxArguments = 10, + + /// MaxRanges - The maximum number of ranges we can hold. + MaxRanges = 10, + + /// MaxFixItHints - The maximum number of ranges we can hold. + MaxFixItHints = 10 }; /// NumDiagArgs - This contains the number of entries in Arguments. signed char NumDiagArgs; - /// NumRanges - This is the number of ranges in the DiagRanges array. + /// NumDiagRanges - This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; - /// \brief The number of code modifications hints in the - /// FixItHints array. - unsigned char NumFixItHints; + /// NumDiagFixItHints - This is the number of hints in the DiagFixItHints + /// array. + unsigned char NumDiagFixItHints; /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum /// values, with one for each argument. This specifies whether the argument @@ -614,15 +669,27 @@ private: /// sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; - /// DiagRanges - The list of ranges added to this diagnostic. It currently - /// only support 10 ranges, could easily be extended if needed. - CharSourceRange DiagRanges[10]; + /// DiagRanges - The list of ranges added to this diagnostic. + CharSourceRange DiagRanges[MaxRanges]; - enum { MaxFixItHints = 6 }; + /// FixItHints - If valid, provides a hint with some code to insert, remove, + /// or modify at a particular position. + FixItHint DiagFixItHints[MaxFixItHints]; - /// FixItHints - If valid, provides a hint with some code - /// to insert, remove, or modify at a particular position. - FixItHint FixItHints[MaxFixItHints]; + DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) { + bool isPragma = L.isValid(); + DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make( + Map, /*IsUser=*/true, isPragma); + + // If this is a pragma mapping, then set the diagnostic mapping flags so + // that we override command line options. + if (isPragma) { + MappingInfo.setNoWarningAsError(true); + MappingInfo.setNoErrorAsFatal(true); + } + + return MappingInfo; + } /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. @@ -633,6 +700,24 @@ private: return Diags->ProcessDiag(*this); } + /// @name Diagnostic Emission + /// @{ +protected: + // Sema requires access to the following functions because the current design + // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to + // access us directly to ensure we minimize the emitted code for the common + // Sema::Diag() patterns. + friend class Sema; + + /// \brief Emit the current diagnostic and clear the diagnostic state. + bool EmitCurrentDiagnostic(); + + unsigned getCurrentDiagID() const { return CurDiagID; } + + SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } + + /// @} + friend class ASTReader; friend class ASTWriter; }; @@ -685,37 +770,39 @@ public: /// for example. class DiagnosticBuilder { mutable DiagnosticsEngine *DiagObj; - mutable unsigned NumArgs, NumRanges, NumFixItHints; + mutable unsigned NumArgs, NumRanges, NumFixits; + + /// \brief Status variable indicating if this diagnostic is still active. + /// + // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), + // but LLVM is not currently smart enough to eliminate the null check that + // Emit() would end up with if we used that as our status variable. + mutable bool IsActive; void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT friend class DiagnosticsEngine; explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) - : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {} + : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true) { + assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); + } friend class PartialDiagnostic; protected: - void FlushCounts(); - -public: - /// Copy constructor. When copied, this "takes" the diagnostic info from the - /// input and neuters it. - DiagnosticBuilder(const DiagnosticBuilder &D) { - DiagObj = D.DiagObj; - D.DiagObj = 0; - NumArgs = D.NumArgs; - NumRanges = D.NumRanges; - NumFixItHints = D.NumFixItHints; + void FlushCounts() { + DiagObj->NumDiagArgs = NumArgs; + DiagObj->NumDiagRanges = NumRanges; + DiagObj->NumDiagFixItHints = NumFixits; } - /// \brief Simple enumeration value used to give a name to the - /// suppress-diagnostic constructor. - enum SuppressKind { Suppress }; + /// \brief Clear out the current diagnostic. + void Clear() const { + DiagObj = 0; + IsActive = false; + } - /// \brief Create an empty DiagnosticBuilder object that represents - /// no actual diagnostic. - explicit DiagnosticBuilder(SuppressKind) - : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { } + /// isActive - Determine whether this diagnostic is still active. + bool isActive() const { return IsActive; } /// \brief Force the diagnostic builder to emit the diagnostic now. /// @@ -724,25 +811,40 @@ public: /// /// \returns true if a diagnostic was emitted, false if the /// diagnostic was suppressed. - bool Emit(); + bool Emit() { + // If this diagnostic is inactive, then its soul was stolen by the copy ctor + // (or by a subclass, as in SemaDiagnosticBuilder). + if (!isActive()) return false; - /// Destructor - The dtor emits the diagnostic if it hasn't already - /// been emitted. - ~DiagnosticBuilder() { Emit(); } + // When emitting diagnostics, we set the final argument count into + // the DiagnosticsEngine object. + FlushCounts(); - /// isActive - Determine whether this diagnostic is still active. - bool isActive() const { return DiagObj != 0; } + // Process the diagnostic. + bool Result = DiagObj->EmitCurrentDiagnostic(); - /// \brief Retrieve the active diagnostic ID. - /// - /// \pre \c isActive() - unsigned getDiagID() const { - assert(isActive() && "DiagnosticsEngine is inactive"); - return DiagObj->CurDiagID; + // This diagnostic is dead. + Clear(); + + return Result; } - /// \brief Clear out the current diagnostic. - void Clear() { DiagObj = 0; } +public: + /// Copy constructor. When copied, this "takes" the diagnostic info from the + /// input and neuters it. + DiagnosticBuilder(const DiagnosticBuilder &D) { + DiagObj = D.DiagObj; + IsActive = D.IsActive; + D.Clear(); + NumArgs = D.NumArgs; + NumRanges = D.NumRanges; + NumFixits = D.NumFixits; + } + + /// Destructor - The dtor emits the diagnostic. + ~DiagnosticBuilder() { + Emit(); + } /// Operator bool: conversion of DiagnosticBuilder to bool always returns /// true. This allows is to be used in boolean error contexts like: @@ -750,38 +852,33 @@ public: operator bool() const { return true; } void AddString(StringRef S) const { + assert(isActive() && "Clients must not add to cleared diagnostic!"); assert(NumArgs < DiagnosticsEngine::MaxArguments && "Too many arguments to diagnostic!"); - if (DiagObj) { - DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string; - DiagObj->DiagArgumentsStr[NumArgs++] = S; - } + DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string; + DiagObj->DiagArgumentsStr[NumArgs++] = S; } void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { + assert(isActive() && "Clients must not add to cleared diagnostic!"); assert(NumArgs < DiagnosticsEngine::MaxArguments && "Too many arguments to diagnostic!"); - if (DiagObj) { - DiagObj->DiagArgumentsKind[NumArgs] = Kind; - DiagObj->DiagArgumentsVal[NumArgs++] = V; - } + DiagObj->DiagArgumentsKind[NumArgs] = Kind; + DiagObj->DiagArgumentsVal[NumArgs++] = V; } void AddSourceRange(const CharSourceRange &R) const { - assert(NumRanges < - sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && + assert(isActive() && "Clients must not add to cleared diagnostic!"); + assert(NumRanges < DiagnosticsEngine::MaxRanges && "Too many arguments to diagnostic!"); - if (DiagObj) - DiagObj->DiagRanges[NumRanges++] = R; + DiagObj->DiagRanges[NumRanges++] = R; } void AddFixItHint(const FixItHint &Hint) const { - assert(NumFixItHints < DiagnosticsEngine::MaxFixItHints && - "Too many fix-it hints!"); - if (NumFixItHints >= DiagnosticsEngine::MaxFixItHints) - return; // Don't crash in release builds - if (DiagObj) - DiagObj->FixItHints[NumFixItHints++] = Hint; + assert(isActive() && "Clients must not add to cleared diagnostic!"); + assert(NumFixits < DiagnosticsEngine::MaxFixItHints && + "Too many arguments to diagnostic!"); + DiagObj->DiagFixItHints[NumFixits++] = Hint; } }; @@ -849,7 +946,8 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const FixItHint &Hint) { - DB.AddFixItHint(Hint); + if (!Hint.isNull()) + DB.AddFixItHint(Hint); return DB; } @@ -951,17 +1049,22 @@ public: return DiagObj->DiagRanges[Idx]; } + /// \brief Return an array reference for this diagnostic's ranges. + ArrayRef<CharSourceRange> getRanges() const { + return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges); + } + unsigned getNumFixItHints() const { - return DiagObj->NumFixItHints; + return DiagObj->NumDiagFixItHints; } const FixItHint &getFixItHint(unsigned Idx) const { - return DiagObj->FixItHints[Idx]; + assert(Idx < getNumFixItHints() && "Invalid index!"); + return DiagObj->DiagFixItHints[Idx]; } const FixItHint *getFixItHints() const { - return DiagObj->NumFixItHints? - &DiagObj->FixItHints[0] : 0; + return getNumFixItHints()? DiagObj->DiagFixItHints : 0; } /// FormatDiagnostic - Format this diagnostic into a string, substituting the @@ -1012,11 +1115,20 @@ public: range_iterator range_begin() const { return Ranges.begin(); } range_iterator range_end() const { return Ranges.end(); } unsigned range_size() const { return Ranges.size(); } + + ArrayRef<CharSourceRange> getRanges() const { + return llvm::makeArrayRef(Ranges); + } + typedef std::vector<FixItHint>::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(); } + + ArrayRef<FixItHint> getFixIts() const { + return llvm::makeArrayRef(FixIts); + } }; /// DiagnosticConsumer - This is an abstract interface implemented by clients of @@ -1031,6 +1143,7 @@ public: unsigned getNumErrors() const { return NumErrors; } unsigned getNumWarnings() const { return NumWarnings; } + virtual void clear() { NumWarnings = NumErrors = 0; } virtual ~DiagnosticConsumer(); @@ -1053,6 +1166,10 @@ public: /// objects made available via \see BeginSourceFile() are inaccessible. virtual void EndSourceFile() {} + /// \brief Callback to inform the diagnostic client that processing of all + /// source files has ended. + virtual void finish() {} + /// IncludeInDiagnosticCounts - This method (whose default implementation /// returns true) indicates whether the diagnostics handled by this /// DiagnosticConsumer should be included in the number of diagnostics @@ -1075,6 +1192,7 @@ public: /// IgnoringDiagConsumer - This is a diagnostic client that just ignores all /// diags. class IgnoringDiagConsumer : public DiagnosticConsumer { + virtual void anchor(); void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { // Just ignore it. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td index 8ae69fe..109cd08 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td @@ -62,8 +62,6 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> { DiagMapping DefaultMapping = defaultmapping; DiagGroup Group; string CategoryName = ""; - string Brief = ""; - string Explanation = ""; } class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>; @@ -87,12 +85,6 @@ class DefaultWarnShowInSystemHeader { class NoSFINAE { bit SFINAE = 0; } class AccessControl { bit AccessControl = 1; } -class Brief<string str> { string Brief = str; } -class FullExplanation<string brief, string full> { - string Brief = brief; - string Explanation = full; -} - // Definitions for Diagnostics. include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" @@ -102,4 +94,5 @@ include "DiagnosticFrontendKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" include "DiagnosticSemaKinds.td" +include "DiagnosticSerializationKinds.td" diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td index 705c95b..9cfe5ef 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -9,9 +9,103 @@ let Component = "AST" in { -//def note_comma_in_ice : Note< -// "C does not permit evaluated commas in an integer constant expression">; +// Constant expression diagnostics. These (and their users) belong in Sema. def note_expr_divide_by_zero : Note<"division by zero">; +def note_constexpr_invalid_cast : Note< + "%select{reinterpret_cast|dynamic_cast|cast which performs the conversions of" + " a reinterpret_cast|cast from %1}0 is not allowed in a constant expression">; +def note_constexpr_invalid_downcast : Note< + "cannot cast object of dynamic type %0 to type %1">; +def note_constexpr_overflow : Note< + "value %0 is outside the range of representable values of type %1">; +def note_constexpr_negative_shift : Note<"negative shift count %0">; +def note_constexpr_large_shift : Note< + "shift count %0 >= width of type %1 (%2 bit%s2)">; +def note_constexpr_lshift_of_negative : Note<"left shift of negative value %0">; +def note_constexpr_lshift_discards : Note<"signed left shift discards bits">; +def note_constexpr_invalid_function : Note< + "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot " + "be used in a constant expression">; +def note_constexpr_virtual_call : Note< + "cannot evaluate virtual function call in a constant expression">; +def note_constexpr_virtual_base : Note< + "cannot construct object of type %0 with virtual base class " + "in a constant expression">; +def note_constexpr_nonliteral : Note< + "non-literal type %0 cannot be used in a constant expression">; +def note_constexpr_non_global : Note< + "%select{pointer|reference}0 to %select{|subobject of }1" + "%select{temporary|%3}2 is not a constant expression">; +def note_constexpr_array_index : Note<"cannot refer to element %0 of " + "%select{array of %2 elements|non-array object}1 in a constant expression">; +def note_constexpr_float_arithmetic : Note< + "floating point arithmetic produces %select{an infinity|a NaN}0">; +def note_constexpr_pointer_subtraction_not_same_array : Note< + "subtracted pointers are not elements of the same array">; +def note_constexpr_pointer_comparison_base_classes : Note< + "comparison of addresses of subobjects of different base classes " + "has unspecified value">; +def note_constexpr_pointer_comparison_base_field : Note< + "comparison of address of base class subobject %0 of class %1 to field %2 " + "has unspecified value">; +def note_constexpr_pointer_comparison_differing_access : Note< + "comparison of address of fields %0 and %2 of %4 with differing access " + "specifiers (%1 vs %3) has unspecified value">; +def note_constexpr_compare_virtual_mem_ptr : Note< + "comparison of pointer to virtual member function %0 has unspecified value">; +def note_constexpr_past_end : Note< + "dereferenced pointer past the end of %select{|subobject of }0" + "%select{temporary|%2}1 is not a constant expression">; +def note_constexpr_past_end_subobject : Note< + "cannot %select{access base class of|access derived class of|access field of|" + "access array element of|ERROR|call member function on|" + "access real component of|access imaginary component of}0 " + "pointer past the end of object">; +def note_constexpr_null_subobject : Note< + "cannot %select{access base class of|access derived class of|access field of|" + "access array element of|perform pointer arithmetic on|" + "call member function on|access real component of|" + "access imaginary component of}0 null pointer">; +def note_constexpr_var_init_non_constant : Note< + "initializer of %0 is not a constant expression">; +def note_constexpr_typeid_polymorphic : Note< + "typeid applied to expression of polymorphic type %0 is " + "not allowed in a constant expression">; +def note_constexpr_void_comparison : Note< + "comparison between unequal pointers to void has unspecified result">; +def note_constexpr_temporary_here : Note<"temporary created here">; +def note_constexpr_conditional_never_const : Note< + "both arms of conditional operator are unable to produce a " + "constant expression">; +def note_constexpr_depth_limit_exceeded : Note< + "constexpr evaluation exceeded maximum depth of %0 calls">; +def note_constexpr_call_limit_exceeded : Note< + "constexpr evaluation hit maximum call limit">; +def note_constexpr_lifetime_ended : Note< + "read of %select{temporary|variable}0 whose lifetime has ended">; +def note_constexpr_ltor_volatile_type : Note< + "read of volatile-qualified type %0 is not allowed in a constant expression">; +def note_constexpr_ltor_volatile_obj : Note< + "read of volatile %select{temporary|object %1|member %1}0 is not allowed in " + "a constant expression">; +def note_constexpr_ltor_mutable : Note< + "read of mutable member %0 is not allowed in a constant expression">; +def note_constexpr_ltor_non_const_int : Note< + "read of non-const variable %0 is not allowed in a constant expression">; +def note_constexpr_ltor_non_constexpr : Note< + "read of non-constexpr variable %0 is not allowed in a constant expression">; +def note_constexpr_read_past_end : Note< + "read of dereferenced one-past-the-end pointer is not allowed in a " + "constant expression">; +def note_constexpr_read_inactive_union_member : Note< + "read of member %0 of union with %select{active member %2|no active member}1 " + "is not allowed in a constant expression">; +def note_constexpr_read_uninit : Note< + "read of uninitialized object is not allowed in a constant expression">; +def note_constexpr_calls_suppressed : Note< + "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to " + "see all)">; +def note_constexpr_call_here : Note<"in call to '%0'">; // inline asm related. let CategoryName = "Inline Assembly Issue" in { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td index 46dc0e6..5461212 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td @@ -9,7 +9,4 @@ let Component = "Analysis" in { -// CHECK: use of uninitialized values -def warn_uninit_val : Warning<"use of uninitialized variable">; - } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td index f9a910a..103fc00 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -18,6 +18,7 @@ let Component = "Common" in { def fatal_too_many_errors : Error<"too many errors emitted, stopping now">, DefaultFatal; +def note_declared_at : Note<"declared here">; def note_previous_definition : Note<"previous definition is here">; def note_previous_declaration : Note<"previous declaration is here">; def note_previous_implicit_declaration : Note< @@ -40,6 +41,12 @@ def err_expected_colon : Error<"expected ':'">; def err_expected_colon_after_setter_name : Error< "method name referenced in property setter attribute " "must end with ':'">; +def err_invalid_string_udl : Error< + "string literal with user-defined suffix cannot be used here">; +def err_invalid_character_udl : Error< + "character literal with user-defined suffix cannot be used here">; +def err_invalid_numeric_udl : Error< + "numeric literal with user-defined suffix cannot be used here">; // Parse && Sema def ext_no_declarators : ExtWarn<"declaration does not declare anything">, @@ -58,8 +65,6 @@ def warn_cxx98_compat_variadic_templates : InGroup<CXX98Compat>, DefaultIgnore; def err_default_special_members : Error< "only special member functions may be defaulted">; -def err_friends_define_only_namespace_scope : Error< - "cannot define a function with non-namespace scope in a friend declaration">; def err_deleted_non_function : Error< "only functions can have deleted definitions">; def err_module_not_found : Error<"module '%0' not found">, DefaultFatal; @@ -83,8 +88,8 @@ def warn_integer_too_large_for_signed : Warning< "integer constant is so large that it is unsigned">; // Sema && AST -def note_invalid_subexpr_in_ice : Note< - "subexpression not valid in an integer constant expression">; +def note_invalid_subexpr_in_const_expr : Note< + "subexpression not valid in a constant expression">; // Targets diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td index 3c0e4f5..b443159 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -18,6 +18,10 @@ def err_drv_unknown_stdin_type : Error< def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_invalid_rtlib_name : Error< + "invalid runtime library name in argument '%0'">; +def err_drv_unsupported_rtlib_for_platform : Error< + "unsupported runtime library '%0' for platform '%1'">; def err_drv_invalid_stdlib_name : Error< "invalid library name in argument '%0'">; def err_drv_invalid_opt_with_multiple_archs : Error< @@ -38,7 +42,7 @@ def err_drv_command_failure : Error< def err_drv_invalid_darwin_version : Error< "invalid Darwin version number: %0">; def err_drv_missing_argument : Error< - "argument to '%0' is missing (expected %1 %plural{1:value|:values}1)">; + "argument to '%0' is missing (expected %1 value%s1)">; def err_drv_invalid_Xarch_argument_with_args : Error< "invalid Xarch argument: '%0', options requiring arguments are unsupported">; def err_drv_invalid_Xarch_argument_isdriver : Error< @@ -62,11 +66,13 @@ def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error< def err_drv_command_failed : Error< "%0 command failed with exit code %1 (use -v to see invocation)">; def err_drv_command_signalled : Error< - "%0 command failed due to signal %1 (use -v to see invocation)">; + "%0 command failed due to signal (use -v to see invocation)">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; def err_drv_invalid_libcxx_deployment : Error< "invalid deployment target for -stdlib=libc++ (requires %0 or later)">; +def err_drv_invalid_feature : Error< + "invalid feature '%0' for CPU '%1'">; def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; @@ -89,21 +95,23 @@ def err_drv_objc_gc_arr : Error< "cannot specify both '-fobjc-arc' and '%0'">; def err_arc_nonfragile_abi : Error< "-fobjc-arc is not supported with fragile abi">; +def err_arc_unsupported : Error< + "-fobjc-arc is not supported on current deployment target">; def err_drv_mg_requires_m_or_mm : Error< "option '-MG' requires '-M' or '-MM'">; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; -def warn_drv_unsupported_option_argument : Warning< - "ignoring unsupported argument '%1' to option '%0'">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; def warn_drv_preprocessed_input_file_unused : Warning< "%0: previously preprocessed input unused when '%1' is present">; def warn_drv_unused_argument : Warning< - "argument unused during compilation: '%0'">; -def warn_drv_pipe_ignored_with_save_temps : Warning< - "-pipe ignored because -save-temps specified">; + "argument unused during compilation: '%0'">, + InGroup<DiagGroup<"unused-command-line-argument">>; +def warn_drv_empty_joined_argument : Warning< + "joined argument expects addition arg: '%0'">, + InGroup<DiagGroup<"unused-command-line-argument">>; def warn_drv_not_using_clang_cpp : Warning< "not using the clang preprocessor due to user override">; def warn_drv_not_using_clang_cxx : Warning< @@ -116,8 +124,6 @@ def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; def warn_ignoring_ftabstop_value : Warning< "ignoring invalid -ftabstop value '%0', using default value %1">; -def warn_drv_conflicting_deployment_targets : Warning< - "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">, InGroup<Deprecated>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td index fffa42f..5d6b887 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -13,12 +13,12 @@ def err_fe_error_opening : Error<"error opening '%0': %1">; def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; -def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; -def err_fe_invalid_ast_action : Error<"invalid action for AST input">, - DefaultFatal; + // Error generated by the backend. def err_fe_inline_asm : Error<"%0">, CatInlineAsm; def note_fe_inline_asm_here : Note<"instantiated into assembly here">; +def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">, + DefaultFatal; @@ -26,16 +26,8 @@ def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, DefaultFatal; -def err_fe_stderr_binary : Error<"unable to change standard error to binary">, - DefaultFatal; def err_fe_dependency_file_requires_MT : Error< "-dependency-file requires at least one -MT or -MQ option">; -def err_fe_incompatible_options : Error< - "'%0' cannot be used with '%1'">, DefaultFatal; -def err_fe_no_fixit_and_codegen : Error< - "FIX-ITs cannot be applied when generating code">; -def err_fe_unable_to_find_fixit_file : Error< - "FIX-IT could not find file '%0'">; def err_fe_invalid_plugin_name : Error< "unable to find plugin '%0'">; def err_fe_expected_compiler_job : Error< @@ -54,19 +46,6 @@ def err_fe_unable_to_create_target : Error< "unable to create target: '%0'">; def err_fe_unable_to_interface_with_target : Error< "unable to interface with target machine">; -def err_fe_unable_to_read_pch_file : Error< - "unable to read PCH file: '%0'">; -def err_fe_not_a_pch_file : Error< - "input is not a PCH file: '%0'">; -def err_fe_pch_malformed : Error< - "malformed or corrupted PCH file: '%0'">, DefaultFatal; -def err_fe_pch_malformed_block : Error< - "malformed block record in PCH file: '%0'">, DefaultFatal; -def err_fe_pch_error_at_end_block : Error< - "error at end of module block in PCH file: '%0'">, DefaultFatal; -def err_fe_pch_file_modified : Error< - "file '%0' has been modified since the precompiled header was built">, - DefaultFatal; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; def err_fe_unable_to_rename_temp : Error< @@ -82,6 +61,10 @@ def warn_fe_cc_print_header_failure : Warning< def warn_fe_cc_log_diagnostics_failure : Warning< "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; +def warn_fe_serialized_diag_failure : Warning< + "unable to open file %0 for serializing diagnostics (%1)">, + InGroup<DiagGroup<"serialized-diagnostics">>; + def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< @@ -98,54 +81,25 @@ def note_fixit_in_macro : Note< def note_fixit_failed : Note< "FIX-IT unable to apply suggested code changes">; def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">; -def note_fixit_main_file_unchanged : Note< - "main file unchanged">; def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; -def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal; - // PCH reader def err_relocatable_without_isysroot : Error< "must specify system root with -isysroot when building a relocatable " "PCH file">; -def warn_pch_target_triple : Error< - "PCH file was compiled for the target '%0' but the current translation " - "unit is being compiled for target '%1'">; -def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " - "PCH file but is currently %select{disabled|enabled}2">; -def err_pch_langopt_value_mismatch : Error< - "%0 differs in PCH file vs. current file">; - -def warn_pch_version_too_old : Error< - "PCH file uses an older PCH format that is no longer supported">; -def warn_pch_version_too_new : Error< - "PCH file uses a newer PCH format that cannot be read">; -def warn_pch_different_branch : Error< - "PCH file built from a different branch (%0) than the compiler (%1)">; -def warn_cmdline_conflicting_macro_def : Error< - "definition of the macro '%0' conflicts with the definition used to " - "build the precompiled header">; -def note_pch_macro_defined_as : Note< - "definition of macro '%0' in the precompiled header">; -def warn_cmdline_missing_macro_defs : Warning< - "macro definitions used to build the precompiled header are missing">; -def note_using_macro_def_from_pch : Note< - "using this macro definition from precompiled header">; -def warn_macro_name_used_in_pch : Error< - "definition of macro %0 conflicts with an identifier used in the " - "precompiled header">; -def warn_pch_compiler_options_mismatch : Error< - "compiler options used when building the precompiled header differ from " - "the options used when using the precompiled header">; -def err_not_a_pch_file : Error< - "'%0' does not appear to be a precompiled header file">, DefaultFatal; def warn_unknown_warning_option : Warning< "unknown warning option '%0'">, InGroup<DiagGroup<"unknown-warning-option"> >; def warn_unknown_negative_warning_option : Warning< - "unknown warning option '%0'">, + "unknown warning option '%0'?">, + InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore; +def warn_unknown_warning_option_suggest : Warning< + "unknown warning option '%0'; did you mean '%1'?">, + InGroup<DiagGroup<"unknown-warning-option"> >; +def warn_unknown_negative_warning_option_suggest : Warning< + "unknown warning option '%0'; did you mean '%1'?">, InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, @@ -158,4 +112,23 @@ def warn_incompatible_analyzer_plugin_api : Warning< InGroup<DiagGroup<"analyzer-incompatible-plugin"> >; def note_incompatible_analyzer_plugin_api : Note< "current API version is '%0', but plugin was compiled with version '%1'">; + +def err_module_map_not_found : Error<"module map file '%0' not found">, + DefaultFatal; +def err_missing_module_name : Error< + "no module name provided; specify one with -fmodule-name=">, + DefaultFatal; +def err_missing_module : Error< + "no module named '%0' declared in module map file '%1'">, DefaultFatal; +def err_missing_umbrella_header : Error< + "cannot open umbrella header '%0': %1">, DefaultFatal; +def err_no_submodule : Error<"no submodule named %0 in module '%1'">; +def err_no_submodule_suggest : Error< + "no submodule named %0 in module '%1'; did you mean '%2'?">; +def warn_missing_submodule : Warning<"missing submodule '%0'">, + InGroup<IncompleteUmbrella>; +def err_module_map_temp_file : Error< + "unable to write temporary module map file '%0'">, DefaultFatal; +def err_module_unavailable : Error<"module '%0' requires feature '%1'">; + } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td index 00a6663..c839853 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -25,7 +25,14 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; def Availability : DiagGroup<"availability">; -def BoolConversions : DiagGroup<"bool-conversions">; +def AutoImport : DiagGroup<"auto-import">; +def ConstantConversion : DiagGroup<"constant-conversion">; +def LiteralConversion : DiagGroup<"literal-conversion">; +def StringConversion : DiagGroup<"string-conversion">; +def SignConversion : DiagGroup<"sign-conversion">; +def BoolConversion : DiagGroup<"bool-conversion">; +def IntConversion : DiagGroup<"int-conversion">; +def NullConversion : DiagGroup<"null-conversion">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; def CXXCompat: DiagGroup<"c++-compat">; def CastAlign : DiagGroup<"cast-align">; @@ -55,34 +62,63 @@ def ExtraTokens : DiagGroup<"extra-tokens">; def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; -def CXX98Compat : DiagGroup<"c++98-compat">; +def CXX98CompatBindToTemporaryCopy : + DiagGroup<"c++98-compat-bind-to-temporary-copy">; +def CXX98CompatLocalTypeTemplateArgs : + DiagGroup<"c++98-compat-local-type-template-args">; +def CXX98CompatUnnamedTypeTemplateArgs : + DiagGroup<"c++98-compat-unnamed-type-template-args">; + +def CXX98Compat : DiagGroup<"c++98-compat", + [CXX98CompatBindToTemporaryCopy, + CXX98CompatLocalTypeTemplateArgs, + CXX98CompatUnnamedTypeTemplateArgs]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; + +// Original name of this warning in Clang def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>; -def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing]>; +// Name of this warning in GCC +def : DiagGroup<"narrowing", [CXX11Narrowing]>; + +def CXX11CompatReservedUserDefinedLiteral : + DiagGroup<"c++11-compat-reserved-user-defined-literal">; +def ReservedUserDefinedLiteral : + DiagGroup<"reserved-user-defined-literal", + [CXX11CompatReservedUserDefinedLiteral]>; + +def CXX11Compat : DiagGroup<"c++11-compat", + [CXX11Narrowing, + CXX11CompatReservedUserDefinedLiteral]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def : DiagGroup<"effc++">; def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; +def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; def FourByteMultiChar : DiagGroup<"four-char-constants">; def GlobalConstructors : DiagGroup<"global-constructors">; def : DiagGroup<"idiomatic-parentheses">; def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; +def DanglingElse: DiagGroup<"dangling-else">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types">; +def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; +def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; def : DiagGroup<"init-self">; def : DiagGroup<"inline">; def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"invalid-pch">; def LiteralRange : DiagGroup<"literal-range">; -def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">; +def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args", + [CXX98CompatLocalTypeTemplateArgs]>; def MalformedWarningCheck : DiagGroup<"malformed-warning-check">; def Main : DiagGroup<"main">; +def MainReturnType : DiagGroup<"main-return-type">; def MissingBraces : DiagGroup<"missing-braces">; def MissingDeclarations: DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; @@ -95,31 +131,37 @@ def LongLong : DiagGroup<"long-long">; def MismatchedTags : DiagGroup<"mismatched-tags">; def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; def ModuleBuild : DiagGroup<"module-build">; +def NullCharacter : DiagGroup<"null-character">; def NullDereference : DiagGroup<"null-dereference">; def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; +def OveralignedType : DiagGroup<"over-aligned">; def : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; def : DiagGroup<"overflow">; def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; +def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">; -def ObjCContinuationPropertyType :DiagGroup<"objc-continuation-property-type">; +def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">; +def ObjCRootClass : DiagGroup<"objc-root-class">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; def PoundWarning : DiagGroup<"#warnings">, DiagCategory<"#warning Directive">; -def PoundPragmaMessage : DiagGroup<"#pragma messages">, +def PoundPragmaMessage : DiagGroup<"#pragma-messages">, DiagCategory<"#pragma message Directive">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; -def ReturnType : DiagGroup<"return-type">; -def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">; +def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; +def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; +def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", + [CXX98CompatBindToTemporaryCopy]>; def SelfAssignment : DiagGroup<"self-assign">; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; @@ -133,6 +175,8 @@ def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; +def StringPlusInt : DiagGroup<"string-plus-int">; +def StrncatSize : DiagGroup<"strncat-size">; def TautologicalCompare : DiagGroup<"tautological-compare">; def HeaderHygiene : DiagGroup<"header-hygiene">; @@ -155,18 +199,25 @@ def : DiagGroup<"strict-overflow=5">; def : DiagGroup<"strict-overflow">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">; +def LambdaExtensions : DiagGroup<"lambda-extensions">; def : DiagGroup<"strict-prototypes">; def StrictSelector : DiagGroup<"strict-selector-match">; +def MethodDuplicate : DiagGroup<"duplicate-method-match">; +def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchEnum : DiagGroup<"switch-enum">; -def Switch : DiagGroup<"switch", [SwitchEnum]>; +def Switch : DiagGroup<"switch">; def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; +def Unicode : DiagGroup<"unicode">; def Uninitialized : DiagGroup<"uninitialized">; def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def UnknownAttributes : DiagGroup<"attributes">; -def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">; +def IgnoredAttributes : DiagGroup<"ignored-attributes">; +def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", + [CXX98CompatUnnamedTypeTemplateArgs]>; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedComparison : DiagGroup<"unused-comparison">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; @@ -205,9 +256,11 @@ def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; def : DiagGroup<"variadic-macros">; def VariadicMacros : DiagGroup<"variadic-macros">; -def VectorConversions : DiagGroup<"vector-conversions">; // clang specific +def VectorConversion : DiagGroup<"vector-conversion">; // clang specific +def VexingParse : DiagGroup<"vexing-parse">; def VLA : DiagGroup<"vla">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; +def Visibility : DiagGroup<"visibility">; // GCC calls -Wdeprecated-writable-strings -Wwrite-strings. def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>; @@ -226,7 +279,8 @@ def ParenthesesOnEquality : DiagGroup<"parentheses-equality">; def Parentheses : DiagGroup<"parentheses", [LogicalOpParentheses, BitwiseOpParentheses, - ParenthesesOnEquality]>; + ParenthesesOnEquality, + DanglingElse]>; // -Wconversion has its own warnings, but we split a few out for // legacy reasons: @@ -234,13 +288,16 @@ def Parentheses : DiagGroup<"parentheses", // - conversion warnings with constant sources are on by default // - conversion warnings for literals are on by default // - bool-to-pointer conversion warnings are on by default +// - __null-to-integer conversion warnings are on by default def Conversion : DiagGroup<"conversion", [DiagGroup<"shorten-64-to-32">, - DiagGroup<"constant-conversion">, - DiagGroup<"literal-conversion">, - DiagGroup<"string-conversion">, - DiagGroup<"sign-conversion">, - BoolConversions]>, + ConstantConversion, + LiteralConversion, + StringConversion, + SignConversion, + BoolConversion, + NullConversion, + IntConversion]>, DiagCategory<"Value Conversion Issue">; def Unused : DiagGroup<"unused", @@ -253,6 +310,7 @@ def Unused : DiagGroup<"unused", // Format settings. def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">; def FormatSecurity : DiagGroup<"format-security">; +def FormatNonStandard : DiagGroup<"format-non-iso">; def FormatY2K : DiagGroup<"format-y2k">; def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull, @@ -284,8 +342,8 @@ def Most : DiagGroup<"most", [ Reorder, ReturnType, SelfAssignment, - Switch, SizeofArrayArgument, + StringPlusInt, Trigraphs, Uninitialized, UnknownPragmas, @@ -298,13 +356,23 @@ def Most : DiagGroup<"most", [ // Thread Safety warnings def ThreadSafety : DiagGroup<"thread-safety">; -// -Wall is -Wmost -Wparentheses -Wtop-level-comparison -def : DiagGroup<"all", [Most, Parentheses]>; +// Note that putting warnings in -Wall will not disable them by default. If a +// warning should be active _only_ when -Wall is passed in, mark it as +// DefaultIgnore in addition to putting it here. +def : DiagGroup<"all", [Most, Parentheses, Switch]>; // Aliases. def : DiagGroup<"", [Extra]>; // -W = -Wextra def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment +def : DiagGroup<"conversion-null", + [NullConversion]>; // -Wconversion-null = -Wnull-conversion +def : DiagGroup<"bool-conversions", + [BoolConversion]>; // -Wbool-conversions = -Wbool-conversion +def : DiagGroup<"int-conversions", + [IntConversion]>; // -Wint-conversions = -Wint-conversion +def : DiagGroup<"vector-conversions", + [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. @@ -318,11 +386,16 @@ def : DiagGroup<"c++0x-extensions", [CXX11]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; -// A warning group for warnings about using C1X features as extensions. -def C1X : DiagGroup<"c1x-extensions">; +// A warning group for warnings about using C11 features as extensions. +def C11 : DiagGroup<"c11-extensions">; + +// A warning group for warnings about using C99 features as extensions. +def C99 : DiagGroup<"c99-extensions">; // A warning group for warnings about GCC extensions. def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; +// A warning group for warnings about code that clang accepts but gcc doesn't. +def GccCompat : DiagGroup<"gcc-compat">; // A warning group for warnings about Microsoft extensions. def Microsoft : DiagGroup<"microsoft">; @@ -330,3 +403,13 @@ def Microsoft : DiagGroup<"microsoft">; def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">; def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">; + +// ObjC API warning groups. +def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">; +def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [ + ObjCRedundantLiteralUse + ]>; + +def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [ + ObjCRedundantAPIUse + ]>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h index 16d9b39..a6c22db 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h @@ -31,14 +31,15 @@ namespace clang { namespace diag { // Start position for diagnostics. enum { - DIAG_START_DRIVER = 300, - DIAG_START_FRONTEND = DIAG_START_DRIVER + 100, - DIAG_START_LEX = DIAG_START_FRONTEND + 120, - DIAG_START_PARSE = DIAG_START_LEX + 300, - DIAG_START_AST = DIAG_START_PARSE + 300, - DIAG_START_SEMA = DIAG_START_AST + 100, - DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, - DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 + DIAG_START_DRIVER = 300, + DIAG_START_FRONTEND = DIAG_START_DRIVER + 100, + DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100, + DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, + DIAG_START_PARSE = DIAG_START_LEX + 300, + DIAG_START_AST = DIAG_START_PARSE + 400, + DIAG_START_SEMA = DIAG_START_AST + 100, + DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, + DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; class CustomDiagInfo; @@ -49,7 +50,7 @@ namespace clang { // Get typedefs for common diagnostics. enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER,BRIEF,FULL) ENUM, + SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM, #include "clang/Basic/DiagnosticCommonKinds.inc" NUM_BUILTIN_COMMON_DIAGNOSTICS #undef DIAG @@ -108,7 +109,7 @@ public: /// \brief Used for handling and querying diagnostic IDs. Can be used and shared /// by multiple Diagnostics for multiple translation units. -class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> { +class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { public: /// Level - The level of the diagnostic, after it has been through mapping. enum Level { @@ -182,6 +183,10 @@ public: /// category. static StringRef getCategoryNameFromID(unsigned CategoryID); + /// isARCDiagnostic - Return true if a given diagnostic falls into an + /// ARC diagnostic category; + static bool isARCDiagnostic(unsigned DiagID); + /// \brief Enumeration describing how the the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. enum SFINAEResponse { @@ -218,39 +223,6 @@ public: /// are not SFINAE errors. static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); - /// getName - Given a diagnostic ID, return its name - static StringRef getName(unsigned DiagID); - - /// getIdFromName - Given a diagnostic name, return its ID, or 0 - static unsigned getIdFromName(StringRef Name); - - /// getBriefExplanation - Given a diagnostic ID, return a brief explanation - /// of the issue - static StringRef getBriefExplanation(unsigned DiagID); - - /// getFullExplanation - Given a diagnostic ID, return a full explanation - /// of the issue - static StringRef getFullExplanation(unsigned DiagID); - - /// Iterator class used for traversing all statically declared - /// diagnostics. - class diag_iterator { - const void *impl; - - friend class DiagnosticIDs; - diag_iterator(const void *im) : impl(im) {} - public: - diag_iterator &operator++(); - bool operator==(const diag_iterator &x) const { return impl == x.impl; } - bool operator!=(const diag_iterator &x) const { return impl != x.impl; } - - llvm::StringRef getDiagName() const; - unsigned getDiagID() const; - }; - - static diag_iterator diags_begin(); - static diag_iterator diags_end(); - /// \brief Get the set of all diagnostic IDs in the group with the given name. /// /// \param Diags [out] - On return, the diagnostics in the group. @@ -258,6 +230,13 @@ public: bool getDiagnosticsInGroup(StringRef Group, llvm::SmallVectorImpl<diag::kind> &Diags) const; + /// \brief Get the set of all diagnostic IDs. + void getAllDiagnostics(llvm::SmallVectorImpl<diag::kind> &Diags) const; + + /// \brief Get the warning option with the closest edit distance to the given + /// group name. + static StringRef getNearestWarningOption(StringRef Group); + private: /// \brief Get the set of all diagnostic IDs in the given group. /// diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td index 9b3a178..670283e 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -13,16 +13,19 @@ let Component = "Lex", CategoryName = "Lexical or Preprocessor Issue" in { -def null_in_string : Warning<"null character(s) preserved in string literal">; -def null_in_char : Warning<"null character(s) preserved in character literal">; -def null_in_file : Warning<"null character ignored">; +def null_in_string : Warning<"null character(s) preserved in string literal">, + InGroup<NullCharacter>; +def null_in_char : Warning<"null character(s) preserved in character literal">, + InGroup<NullCharacter>; +def null_in_file : Warning<"null character ignored">, InGroup<NullCharacter>; def warn_nested_block_comment : Warning<"'/*' within block comment">, InGroup<Comment>; def escaped_newline_block_comment_end : Warning< "escaped newline between */ characters at block comment end">, InGroup<Comment>; def backslash_newline_space : Warning< - "backslash and newline separated by space">; + "backslash and newline separated by space">, + InGroup<DiagGroup<"backslash-newline-escape">>; // Digraphs. def warn_cxx98_compat_less_colon_colon : Warning< @@ -45,14 +48,21 @@ def ext_bcpl_comment : Extension< InGroup<Comment>; def ext_no_newline_eof : Extension<"no newline at end of file">, InGroup<DiagGroup<"newline-eof">>; -def ext_dollar_in_identifier : Extension<"'$' in identifier">; -def charize_microsoft_ext : Extension<"@# is a microsoft extension">; + +def warn_cxx98_compat_no_newline_eof : Warning< + "C++98 requires newline at end of file">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; + +def ext_dollar_in_identifier : Extension<"'$' in identifier">, + InGroup<DiagGroup<"dollar-in-identifier-extension">>; +def ext_charize_microsoft : Extension<"@# is a microsoft extension">, + InGroup<Microsoft>; def ext_token_used : Extension<"extension used">, InGroup<DiagGroup<"language-extension-token">>; def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">, - InGroup<CXX11Compat>; + InGroup<CXX11Compat>, DefaultIgnore; def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">; def warn_unterminated_char : ExtWarn<"missing terminating ' character">; @@ -90,7 +100,16 @@ def err_hex_escape_no_digits : Error<"\\x used with no following hex digits">; def err_ucn_escape_no_digits : Error<"\\u used with no following hex digits">; def err_ucn_escape_invalid : Error<"invalid universal character">; def err_ucn_escape_incomplete : Error<"incomplete universal character name">; -def err_ucn_escape_too_big : Error<"universal character name is too long">; +def err_ucn_escape_basic_scs : Error< + "character '%0' cannot be specified by a universal character name">; +def err_ucn_control_character : Error< + "universal character name refers to a control character">; +def warn_cxx98_compat_literal_ucn_escape_basic_scs : Warning< + "specifying character '%0' with a universal character name " + "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_literal_ucn_control_character : Warning< + "universal character name referring to a control character " + "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">; def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">; def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">; @@ -102,10 +121,14 @@ def warn_extraneous_char_constant : Warning< "extraneous characters in character constant ignored">; def warn_char_constant_too_large : Warning< "character constant too long for its type">; +def err_multichar_utf_character_literal : Error< + "Unicode character literals may not contain multiple characters">; def err_exponent_has_no_digits : Error<"exponent has no digits">; def ext_imaginary_constant : Extension<"imaginary constants are an extension">; def err_hexconstant_requires_exponent : Error< "hexadecimal floating constants require an exponent">; +def err_hexconstant_requires_digits : Error< + "hexadecimal floating constants require a significand">; def ext_hexconstant_invalid : Extension< "hexadecimal floating constants are a C99 feature">; def ext_binary_literal : Extension< @@ -116,36 +139,69 @@ def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; def ext_string_too_long : Extension<"string literal of length %0 exceeds " "maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to " "support">, InGroup<OverlengthStrings>; -def warn_ucn_escape_too_large : ExtWarn< - "character unicode escape sequence too long for its type">; +def err_character_too_large : Error< + "character too large for enclosing character literal type">; def warn_ucn_not_valid_in_c89 : ExtWarn< - "unicode escape sequences are only valid in C99 or C++">; + "unicode escape sequences are only valid in C99 or C++">, InGroup<Unicode>; def warn_cxx98_compat_unicode_literal : Warning< "unicode literals are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx11_compat_user_defined_literal : Warning< + "identifier after literal will be treated as a user-defined literal suffix " + "in C++11">, InGroup<CXX11Compat>, DefaultIgnore; +def warn_cxx11_compat_reserved_user_defined_literal : Warning< + "identifier after literal will be treated as a reserved user-defined literal " + "suffix in C++11">, + InGroup<CXX11CompatReservedUserDefinedLiteral>, DefaultIgnore; +def ext_reserved_user_defined_literal : ExtWarn< + "invalid suffix on literal; C++11 requires a space between literal and " + "identifier">, InGroup<ReservedUserDefinedLiteral>, DefaultError; +def ext_ms_reserved_user_defined_literal : ExtWarn< + "invalid suffix on literal; C++11 requires a space between literal and " + "identifier">, InGroup<ReservedUserDefinedLiteral>; def err_unsupported_string_concat : Error< "unsupported non-standard concatenation of string literals">; - +def err_string_concat_mixed_suffix : Error< + "differing user-defined suffixes ('%0' and '%1') in string literal " + "concatenation">; +def err_pp_invalid_udl : Error< + "%select{character|integer}0 literal with user-defined suffix " + "cannot be used in preprocessor constant expression">; +def err_bad_string_encoding : Error< + "illegal character encoding in string literal">; +def warn_bad_string_encoding : ExtWarn< + "illegal character encoding in string literal">, + InGroup<DiagGroup<"invalid-source-encoding">>; +def err_bad_character_encoding : Error< + "illegal character encoding in character literal">; +def warn_bad_character_encoding : ExtWarn< + "illegal character encoding in character literal">, + InGroup<DiagGroup<"invalid-source-encoding">>; + + //===----------------------------------------------------------------------===// // PTH Diagnostics //===----------------------------------------------------------------------===// -def err_pth_cannot_read : Error< - "PTH file '%0' could not be read">; def err_invalid_pth_file : Error< "invalid or corrupt PTH file '%0'">; //===----------------------------------------------------------------------===// // Preprocessor Diagnostics //===----------------------------------------------------------------------===// -def pp_hash_warning : Warning<"#warning%0">, + +let CategoryName = "User Defined Issues" in { +def pp_hash_warning : Warning<"%0">, InGroup<PoundWarning>, DefaultWarnShowInSystemHeader; +def err_pp_hash_error : Error<"%0">; +} + def pp_include_next_in_primary : Warning< "#include_next in primary source file">; def pp_include_macros_out_of_predefines : Error< "the #__include_macros directive is only for internal use by -imacros">; def pp_include_next_absolute_path : Warning<"#include_next with absolute path">; def ext_c99_whitespace_required_after_macro_name : ExtWarn< - "ISO C99 requires whitespace after the macro name">; + "ISO C99 requires whitespace after the macro name">, InGroup<C99>; def ext_missing_whitespace_after_macro_name : ExtWarn< "whitespace required after macro name">; def warn_missing_whitespace_after_macro_name : Warning< @@ -160,6 +216,9 @@ def pp_out_of_date_dependency : Warning< def pp_undef_builtin_macro : Warning<"undefining builtin macro">; def pp_redef_builtin_macro : Warning<"redefining builtin macro">, InGroup<DiagGroup<"builtin-macro-redefined">>; +def pp_disabled_macro_expansion : Warning< + "disabled expansion of recursive macro">, DefaultIgnore, + InGroup<DiagGroup<"disabled-macro-expansion">>; def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore, InGroup<DiagGroup<"unused-macros">>; def warn_pp_undef_identifier : Warning< @@ -175,7 +234,11 @@ def warn_pp_convert_lhs_to_positive : Warning< def warn_pp_convert_rhs_to_positive : Warning< "right side of operator converted from negative value to unsigned: %0">; -def ext_pp_import_directive : Extension<"#import is a language extension">; +def ext_pp_import_directive : Extension<"#import is a language extension">, + InGroup<DiagGroup<"import-preprocessor-directive-pedantic">>; +def err_pp_import_directive_ms : Error< + "#import of type library is an unsupported Microsoft feature">; + def ext_pp_ident_directive : Extension<"#ident is a language extension">; def ext_pp_include_next_directive : Extension< "#include_next is a language extension">; @@ -195,8 +258,11 @@ def warn_cxx98_compat_variadic_macro : Warning< InGroup<CXX98CompatPedantic>, DefaultIgnore; def ext_named_variadic_macro : Extension< "named variadic macros are a GNU extension">, InGroup<VariadicMacros>; +def err_embedded_include : Error< + "embedding a #%0 directive within macro arguments is not supported">; def ext_embedded_directive : Extension< - "embedding a directive within macro arguments is not portable">; + "embedding a directive within macro arguments has undefined behavior">, + InGroup<DiagGroup<"embedded-directive">>; def ext_missing_varargs_arg : Extension< "varargs argument missing, but tolerated as an extension">; def ext_empty_fnmacro_arg : Extension< @@ -206,7 +272,6 @@ def warn_cxx98_compat_empty_fnmacro_arg : Warning< InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_pp_invalid_directive : Error<"invalid preprocessing directive">; -def err_pp_hash_error : Error<"#error%0">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; def err_pp_error_opening_file : Error< "error opening file '%0': %1">, DefaultFatal; @@ -236,7 +301,6 @@ def pp_err_else_without_if : Error<"#else without #if">; def pp_err_elif_without_if : Error<"#elif without #if">; def err_pp_endif_without_if : Error<"#endif without #if">; def err_pp_expected_value_in_expr : Error<"expected value in expression">; -def err_pp_missing_val_before_operator : Error<"missing value before operator">; def err_pp_expected_rparen : Error<"expected ')' in preprocessor expression">; def err_pp_expected_eol : Error< "expected end of line in preprocessor expression">; @@ -266,6 +330,19 @@ def warn_has_warning_invalid_option : ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">, InGroup<MalformedWarningCheck>; +def warn_pragma_include_alias_mismatch_angle : + ExtWarn<"angle-bracketed include <%0> cannot be aliased to double-quoted " + "include \"%1\"">, InGroup<UnknownPragmas>; +def warn_pragma_include_alias_mismatch_quote : + ExtWarn<"double-quoted include \"%0\" cannot be aliased to angle-bracketed " + "include <%1>">, InGroup<UnknownPragmas>; +def warn_pragma_include_alias_expected : + ExtWarn<"pragma include_alias expected '%0'">, + InGroup<UnknownPragmas>; +def warn_pragma_include_alias_expected_filename : + ExtWarn<"pragma include_alias expected include filename">, + InGroup<UnknownPragmas>; + def err__Pragma_malformed : Error< "_Pragma takes a parenthesized string literal">; def err_pragma_comment_malformed : Error< @@ -355,7 +432,7 @@ def warn_cxx98_compat_pp_line_too_big : Warning< "#line number greater than 32767 is incompatible with C++98">, InGroup<CXX98CompatPedantic>, DefaultIgnore; -def err_pp_export_non_macro : Error<"no macro named %0 to export">; +def err_pp_visibility_non_macro : Error<"no macro named %0">; def err_pp_arc_cf_code_audited_syntax : Error<"expected 'begin' or 'end'">; def err_pp_double_begin_of_arc_cf_code_audited : Error< @@ -367,4 +444,60 @@ def err_pp_include_in_arc_cf_code_audited : Error< def err_pp_eof_in_arc_cf_code_audited : Error< "'#pragma clang arc_cf_code_audited' was not ended within this file">; +// Module map parsing +def err_mmap_unknown_token : Error<"skipping stray token">; +def err_mmap_expected_module : Error<"expected module declaration">; +def err_mmap_expected_module_name : Error<"expected module name">; +def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">; +def err_mmap_expected_rbrace : Error<"expected '}'">; +def note_mmap_lbrace_match : Note<"to match this '{'">; +def err_mmap_expected_rsquare : Error<"expected ']' to close attribute">; +def note_mmap_lsquare_match : Note<"to match this ']'">; +def err_mmap_expected_member : Error< + "expected umbrella, header, submodule, or module export">; +def err_mmap_expected_header : Error<"expected a header name after '%0'">; +def err_mmap_module_redefinition : Error< + "redefinition of module '%0'">; +def note_mmap_prev_definition : Note<"previously defined here">; +def err_mmap_header_conflict : Error< + "header '%0' is already part of module '%1'">; +def err_mmap_header_not_found : Error< + "%select{|umbrella }0header '%1' not found">; +def err_mmap_umbrella_dir_not_found : Error< + "umbrella directory '%0' not found">; +def err_mmap_umbrella_clash : Error< + "umbrella for module '%0' already covers this directory">; +def err_mmap_export_module_id : Error< + "expected an exported module name or '*'">; +def err_mmap_missing_module_unqualified : Error< + "no module named '%0' visible from '%1'">; +def err_mmap_missing_module_qualified : Error< + "no module named '%0' in '%1'">; +def err_mmap_top_level_inferred_submodule : Error< + "only submodules may be inferred with wildcard syntax">; +def err_mmap_inferred_no_umbrella : Error< + "inferred submodules require a module with an umbrella">; +def err_mmap_inferred_redef : Error< + "redefinition of inferred submodule">; +def err_mmap_expected_lbrace_wildcard : Error< + "expected '{' to start inferred submodule">; +def err_mmap_expected_wildcard_member : Error< + "expected module export wildcard">; +def err_mmap_expected_export_wildcard : Error< + "only '*' can be exported from an inferred submodule">; +def err_mmap_explicit_top_level : Error< + "'explicit' is not permitted on top-level modules">; +def err_mmap_nested_submodule_id : Error< + "qualified module name can only be used to define modules at the top level">; +def err_mmap_expected_feature : Error<"expected a feature name">; +def err_mmap_expected_attribute : Error<"expected an attribute name">; +def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">, + InGroup<IgnoredAttributes>; + +def warn_auto_module_import : Warning< + "treating #%select{include|import|include_next|__include_macros}0 as an " + "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore; +def warn_uncovered_module_header : Warning< + "umbrella header does not include header '%0'">, InGroup<IncompleteUmbrella>; + } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index 73437b2..c183da7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -23,6 +23,9 @@ let CategoryName = "Parse Issue" in { def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; def ext_top_level_semi : Extension< "extra ';' outside of a function">; +def warn_cxx98_compat_top_level_semi : Warning< + "extra ';' outside of a function is incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def ext_extra_struct_semi : Extension< "extra ';' inside a %0">; def ext_extra_ivar_semi : Extension< @@ -35,9 +38,10 @@ def ext_integer_complex : Extension< "complex integer types are an extension">; def ext_thread_before : Extension<"'__thread' before 'static'">; -def ext_empty_struct_union : Extension<"empty %select{struct|union}0 " - "(accepted as an extension) has size 0 in C, size 1 in C++">, - InGroup<CXXCompat>; +def ext_empty_struct_union : Extension< + "empty %select{struct|union}0 is a GNU extension">, InGroup<GNU>; +def warn_empty_struct_union_compat : Warning<"empty %select{struct|union}0 " + "has size 0 in C, size 1 in C++">, InGroup<CXXCompat>, DefaultIgnore; def error_empty_enum : Error<"use of empty enum">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_short_spec : Error<"'short %0' is invalid">; @@ -49,12 +53,17 @@ def err_friend_storage_spec : Error<"'%0' is invalid in friend declarations">; def ext_ident_list_in_param : Extension< "type-less parameter names in function declaration">; def ext_c99_variable_decl_in_for_loop : Extension< - "variable declaration in for loop is a C99-specific feature">; + "variable declaration in for loop is a C99-specific feature">, InGroup<C99>; def ext_c99_compound_literal : Extension< - "compound literals are a C99-specific feature">; + "compound literals are a C99-specific feature">, InGroup<C99>; +def ext_c99_flexible_array_member : Extension< + "Flexible array members are a C99-specific feature">, InGroup<C99>; def ext_enumerator_list_comma : Extension< "commas at the end of enumerator lists are a %select{C99|C++11}0-specific " "feature">; +def warn_cxx98_compat_enumerator_list_comma : Warning< + "commas at the end of enumerator lists are incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_enumerator_list_missing_comma : Error< "missing ',' between enumerators">; def err_enumerator_unnamed_no_def : Error< @@ -62,16 +71,26 @@ def err_enumerator_unnamed_no_def : Error< def ext_ms_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup<Microsoft>; +def warn_cxx98_compat_enum_fixed_underlying_type : Warning< + "enumeration types with a fixed underlying type are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_alignof : Warning< + "alignof expressions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; -def ext_c1x_generic_selection : Extension< - "generic selections are a C1X-specific feature">, InGroup<C1X>; +def warn_microsoft_dependent_exists : Warning< + "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, + InGroup<DiagGroup<"microsoft-exists">>; + +def ext_c11_generic_selection : Extension< + "generic selections are a C11-specific feature">, InGroup<C11>; def err_duplicate_default_assoc : Error< "duplicate default generic association">; def note_previous_default_assoc : Note< "previous default generic association is here">; -def ext_c1x_alignas : Extension< - "_Alignas is a C1X-specific feature">, InGroup<C1X>; +def ext_c11_alignas : Extension< + "_Alignas is a C11-specific feature">, InGroup<C11>; def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNU>; @@ -98,10 +117,10 @@ def ext_gnu_case_range : Extension<"use of GNU case range extension">, InGroup<GNU>; // Generic errors. -def err_parse_error : Error<"parse error">; def err_expected_expression : Error<"expected expression">; def err_expected_type : Error<"expected a type">; def err_expected_external_declaration : Error<"expected external declaration">; +def err_extraneous_closing_brace : Error<"extraneous closing brace ('}')">; def err_expected_ident : Error<"expected identifier">; def err_expected_ident_lparen : Error<"expected identifier or '('">; def err_expected_ident_lbrace : Error<"expected identifier or '{'">; @@ -126,17 +145,24 @@ def err_function_declared_typedef : Error< "function definition declared 'typedef'">; def err_iboutletcollection_builtintype : Error< "type argument of iboutletcollection attribute cannot be a builtin type">; - +def err_iboutletcollection_with_protocol : Error< + "invalid argument of iboutletcollection attribute">; def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">; def err_at_in_class : Error<"unexpected '@' in member specification">; def err_expected_fn_body : Error< "expected function body after function declarator">; +def warn_attribute_on_function_definition : Warning< + "GCC does not allow %0 attribute in this position on a function definition">, + InGroup<GccCompat>; +def warn_attribute_no_decl : Warning< + "attribute %0 ignored, because it is not attached to a declaration">, + InGroup<IgnoredAttributes>; def err_expected_method_body : Error<"expected method body">; def err_invalid_token_after_toplevel_declarator : Error< "expected ';' after top level declarator">; -def err_invalid_equalequal_after_declarator : Error< - "invalid '==' at end of declaration; did you mean '='?">; +def err_invalid_token_after_declarator_suggest_equal : Error< + "invalid '%0' at end of declaration; did you mean '='?">; def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; def err_expected_lparen_after_id : Error<"expected '(' after %0">; @@ -174,8 +200,8 @@ def err_label_end_of_compound_statement : Error< def err_address_of_label_outside_fn : Error< "use of address-of-label extension outside of a function body">; def err_expected_string_literal : Error<"expected string literal">; -def err_expected_asm_operand : Error< - "expected string literal or '[' for asm operand">, CatInlineAsm; +def err_asm_operand_wide_string_literal : Error< + "cannot use %select{unicode|wide}0 string literal in 'asm'">; def err_expected_selector_for_method : Error< "expected selector for Objective-C method">; def err_expected_property_name : Error<"expected property name">; @@ -188,25 +214,45 @@ def err_illegal_decl_reference_to_reference : Error< "%0 declared as a reference to a reference">; def ext_rvalue_reference : ExtWarn< "rvalue references are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_rvalue_reference : Warning< + "rvalue references are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def ext_ref_qualifier : ExtWarn< "reference qualifiers on functions are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_ref_qualifier : Warning< + "reference qualifiers on functions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def ext_inline_namespace : ExtWarn< "inline namespaces are a C++11 feature">, InGroup<CXX11>; -def err_generalized_initializer_lists : Error< - "generalized initializer lists are a C++11 extension unsupported in Clang">; +def warn_cxx98_compat_inline_namespace : Warning< + "inline namespaces are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def ext_generalized_initializer_lists : ExtWarn< - "generalized initializer lists are a C++11 extension unsupported in Clang">, + "generalized initializer lists are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_generalized_initializer_lists : Warning< + "generalized initializer lists are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def err_init_list_bin_op : Error<"initializer list cannot be used on the " + "%select{left|right}0 hand side of operator '%1'">; +def warn_cxx98_compat_trailing_return_type : Warning< + "trailing return types are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def ext_auto_type_specifier : ExtWarn< "'auto' type specifier is a C++11 extension">, InGroup<CXX11>; def warn_auto_storage_class : Warning< "'auto' storage class specifier is redundant and incompatible with C++11">, - InGroup<CXX11Compat>; + InGroup<CXX11Compat>, DefaultIgnore; def ext_auto_storage_class : ExtWarn< "'auto' storage class specifier is not permitted in C++11, and will not " - "be supported in future releases">; + "be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>; def ext_for_range : ExtWarn< "range-based for loop is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_for_range : Warning< + "range-based for loop is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def err_for_range_expected_decl : Error< + "for range declaration must declare a variable">; def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; @@ -214,7 +260,14 @@ def err_missing_comma_before_ellipsis : Error< "C requires a comma prior to the ellipsis in a variadic function type">; def err_unexpected_typedef_ident : Error< "unexpected type name %0: expected identifier">; +def warn_cxx98_compat_decltype : Warning< + "'decltype' type specifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def err_unexpected_scope_on_base_decltype : Error< + "unexpected namespace scope prior to decltype">; def err_expected_class_name : Error<"expected class name">; +def err_expected_class_name_not_template : + Error<"'typename' is redundant; base classes are implicitly types">; def err_unspecified_vla_size_with_static : Error< "'static' may not be used with an unspecified variable length array size">; @@ -228,9 +281,11 @@ def err_typename_invalid_storageclass : Error< "type name does not allow storage class to be specified">; def err_typename_invalid_functionspec : Error< "type name does not allow function specifier to be specified">; +def err_typename_invalid_constexpr : Error< + "type name does not allow constexpr specifier to be specified">; def err_typename_identifiers_only : Error< "typename is allowed for identifiers only">; - + def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; def err_invalid_vector_decl_spec_combination : Error< @@ -255,30 +310,40 @@ def err_templated_using_directive : Error< "cannot template a using directive">; def err_templated_using_declaration : Error< "cannot template a using declaration">; -def err_expected_ident_in_using : Error< - "expected an identifier in using directive">; def err_unexected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier">; def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; -def ext_c1x_static_assert : Extension< - "_Static_assert is a C1X-specific feature">, InGroup<C1X>; +def ext_c11_static_assert : Extension< + "_Static_assert is a C11-specific feature">, InGroup<C11>; +def warn_cxx98_compat_static_assert : Warning< + "static_assert declarations are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< "method type specifier must start with '-' or '+'">; def err_objc_no_attributes_on_category : Error< "attributes may not be specified on a category">; -def err_objc_missing_end : Error<"missing @end">; +def err_objc_missing_end : Error<"missing '@end'">; +def note_objc_container_start : Note< + "%select{class|protocol|category|class extension|implementation" + "|category implementation}0 started here">; def warn_objc_protocol_qualifier_missing_id : Warning< "protocol qualifiers without 'id' is archaic">; def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; def err_illegal_super_cast : Error< "cannot cast 'super' (it isn't an expression)">; +def err_nsnumber_nonliteral_unary : Error< + "@%0 must be followed by a number to form an NSNumber object">; -let CategoryName = "Automatic Reference Counting Issue" in { +let CategoryName = "ARC Parse Issue" in { def err_arc_bridge_retain : Error< "unknown cast annotation __bridge_retain; did you mean __bridge_retained?">; +// To be default mapped to an error later. +def warn_arc_bridge_cast_nonarc : Warning< + "'%0' casts have no effect when not using ARC">, + InGroup<DiagGroup<"arc-bridge-casts-disallowed-in-nonarc">>; } def err_objc_illegal_visibility_spec : Error< @@ -303,13 +368,8 @@ def err_objc_directive_only_in_protocol : Error< def err_missing_catch_finally : Error< "@try statement without a @catch and @finally clause">; def err_objc_concat_string : Error<"unexpected token after Objective-C string">; -def err_missing_sel_definition : Error<"cannot find definition of 'SEL'">; -def err_missing_id_definition : Error<"cannot find definition of 'id'">; -def err_missing_proto_definition : Error< - "cannot find definition of 'Protocol'">; -def err_missing_class_definition : Error<"cannot find definition of 'Class'">; -def err_expected_implementation : Error< - "@end must appear in an @implementation context">; +def err_expected_objc_container : Error< + "'@end' must appear in an Objective-C context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; def err_synthesized_property_name : Error< @@ -332,10 +392,16 @@ def err_func_def_no_params : Error< "function definition does not declare parameters">; def err_expected_lparen_after_type : Error< "expected '(' for function-style cast or type construction">; -def err_expected_equal_after_declarator : Error< - "expected '=' after declarator">; +def err_expected_init_in_condition : Error< + "variable declaration in condition must have an initializer">; +def err_expected_init_in_condition_lparen : Error< + "variable declaration in condition cannot have a parenthesized initializer">; def warn_parens_disambiguated_as_function_decl : Warning< - "parentheses were disambiguated as a function declarator">; + "parentheses were disambiguated as a function declarator">, + InGroup<VexingParse>; +def warn_dangling_else : Warning< + "add explicit braces to avoid dangling else">, + InGroup<DanglingElse>; def err_expected_member_or_base_name : Error< "expected class member or base class name">; def err_expected_lbrace_after_base_specifiers : Error< @@ -344,8 +410,13 @@ def ext_ellipsis_exception_spec : Extension< "exception specification of '...' is a Microsoft extension">; def err_dynamic_and_noexcept_specification : Error< "cannot have both throw() and noexcept() clause on the same function">; +def warn_cxx98_compat_noexcept_decl : Warning< + "noexcept specifications are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; +def err_expected_rbrace_or_comma : Error<"expected '}' or ','">; +def err_expected_rsquare_or_comma : Error<"expected ']' or ','">; def err_using_namespace_in_class : Error< "'using namespace' is not allowed in classes">; def err_destructor_tilde_identifier : Error< @@ -356,13 +427,24 @@ def err_default_arg_unparsed : Error< "unexpected end of default argument expression">; def err_parser_impl_limit_overflow : Error< "parser recursion limit reached, program too complex">, DefaultFatal; +def err_misplaced_ellipsis_in_declaration : Error< + "'...' must %select{immediately precede declared identifier|" + "be innermost component of anonymous pack declaration}0">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; // C++ operator overloading -def err_operator_string_not_empty : Error< +def err_literal_operator_string_prefix : Error< + "string literal after 'operator' cannot have an encoding prefix">; +def err_literal_operator_string_not_empty : Error< "string literal after 'operator' must be '\"\"'">; +def err_literal_operator_missing_space : Error< + "C++11 requires a space between the \"\" and the user-defined suffix in a " + "literal operator">; +def warn_cxx98_compat_literal_operator : Warning< + "literal operators are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; // Classes. def err_anon_type_definition : Error< @@ -371,16 +453,27 @@ def err_default_delete_in_multiple_declaration : Error< "'= %select{default|delete}0' is a function definition and must occur in a " "standalone declaration">; +def warn_cxx98_compat_noexcept_expr : Warning< + "noexcept expressions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_nullptr : Warning< + "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; + def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< "attributes are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def err_cxx0x_attribute_forbids_arguments : Error< - "C++11 attribute '%0' cannot have an argument list">; -def err_cxx0x_attribute_requires_arguments : Error< - "C++1 attribute '%0' must have an argument list">; +def err_cxx11_attribute_forbids_arguments : Error< + "attribute '%0' cannot have an argument list">; +def err_cxx11_attribute_forbids_ellipsis : Error< + "attribute '%0' cannot be used as an attribute pack">; def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; +def err_l_square_l_square_not_attribute : Error< + "C++11 only allows consecutive left square brackets when " + "introducing an attribute">; +def err_alignas_pack_exp_unsupported : Error< + "pack expansions in alignment specifiers are not supported yet">; /// C++ Templates def err_expected_template : Error<"expected template">; @@ -388,23 +481,22 @@ def err_unknown_template_name : Error< "unknown template name %0">; def err_expected_comma_greater : Error< "expected ',' or '>' in template-parameter-list">; -def err_expected_type_id_after : Error<"expected type-id after '%0'">; -def err_expected_class_before : Error<"expected 'class' before '%0'">; +def err_class_on_template_template_param : Error< + "template template parameter requires 'class' after the parameter list">; def err_template_spec_syntax_non_template : Error< "identifier followed by '<' indicates a class template specialization but " "%0 %select{does not refer to a template|refers to a function " "template|<unused>|refers to a template template parameter}1">; def err_id_after_template_in_nested_name_spec : Error< "expected template name after 'template' keyword in nested name specifier">; -def err_id_after_template_in_typename_spec : Error< - "expected template name after 'template' keyword in typename specifier">; -def err_less_after_template_name_in_nested_name_spec : Error< - "expected '<' after 'template %0' in nested name specifier">; def err_two_right_angle_brackets_need_space : Error< "a space is required between consecutive right angle brackets (use '> >')">; def warn_cxx0x_right_shift_in_template_arg : Warning< "use of right-shift operator ('>>') in template argument will require " "parentheses in C++11">; +def warn_cxx98_compat_two_right_angle_brackets : Warning< + "consecutive right angle brackets are incompatible with C++98 (use '> >')">, + InGroup<CXX98Compat>, DefaultIgnore; def err_multiple_template_declarators : Error< "%select{|a template declaration|an explicit template specialization|" "an explicit template instantiation}0 can " @@ -414,12 +506,20 @@ def err_explicit_instantiation_with_definition : Error< "definition is meant to be an explicit specialization, add '<>' after the " "'template' keyword">; def err_enum_template : Error<"enumeration cannot be a template">; +def err_explicit_instantiation_enum : Error< + "enumerations cannot be explicitly instantiated">; +def err_expected_template_parameter : Error<"expected template parameter">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; def warn_missing_dependent_template_keyword : ExtWarn< "use 'template' keyword to treat '%0' as a dependent template name">; +def ext_extern_template : Extension< + "extern templates are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_extern_template : Warning< + "extern templates are incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def warn_static_inline_explicit_inst_ignored : Warning< "ignoring '%select{static|inline}0' keyword on explicit template " "instantiation">; @@ -457,23 +557,31 @@ def err_ctor_init_missing_comma : Error< "missing ',' between base or member initializers">; // C++ declarations -def err_friend_decl_defines_class : Error< +def err_friend_decl_defines_type : Error< "cannot define a type in a friend declaration">; def err_missing_whitespace_digraph : Error< "found '<::' after a " "%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0" " which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">; -def warn_deleted_function_accepted_as_extension: ExtWarn< - "deleted function definition accepted as a C++11 extension">, InGroup<CXX11>; -def warn_defaulted_function_accepted_as_extension: ExtWarn< - "defaulted function definition accepted as a C++11 extension">, - InGroup<CXX11>; +def ext_deleted_function : ExtWarn< + "deleted function definitions are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_deleted_function : Warning< + "deleted function definitions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def ext_defaulted_function : ExtWarn< + "defaulted function definitions are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_defaulted_function : Warning< + "defaulted function definitions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; // C++11 in-class member initialization -def warn_nonstatic_member_init_accepted_as_extension: ExtWarn< - "in-class initialization of non-static data member accepted as a C++11 extension">, +def ext_nonstatic_member_init : ExtWarn< + "in-class initialization of non-static data member is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_nonstatic_member_init : Warning< + "in-class initialization of non-static data members is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_bitfield_member_init: Error< "bitfield member cannot have an in-class initializer">; def err_incomplete_array_member_init: Error< @@ -481,23 +589,30 @@ def err_incomplete_array_member_init: Error< // C++11 alias-declaration def ext_alias_declaration : ExtWarn< - "alias declarations accepted as a C++11 extension">, InGroup<CXX11>; + "alias declarations are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_alias_declaration : Warning< + "alias declarations are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_alias_declaration_not_identifier : Error< "name defined in alias declaration must be an identifier">; def err_alias_declaration_specialization : Error< "%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">; // C++11 override control -def ext_override_control_keyword : Extension< - "'%0' keyword accepted as a C++11 extension">, InGroup<CXX11>; +def ext_override_control_keyword : ExtWarn< + "'%0' keyword is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_override_control_keyword : Warning< + "'%0' keyword is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; -def err_duplicate_class_virt_specifier : Error< - "class already marked '%0'">; def err_scoped_enum_missing_identifier : Error< "scoped enumeration requires a name">; +def warn_cxx98_compat_scoped_enum : Warning< + "scoped enumerations are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_expected_parameter_pack : Error< "expected the name of a parameter pack">; @@ -514,6 +629,11 @@ def err_this_captured_by_reference : Error< def err_expected_capture : Error< "expected variable name or 'this' in lambda capture list">; def err_expected_lambda_body : Error<"expected body of lambda expression">; +def warn_cxx98_compat_lambda : Warning< + "lambda expressions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def err_lambda_missing_parens : Error< + "lambda requires '()' before %select{'mutable'|return type}0">; // Availability attribute def err_expected_version : Error< @@ -554,8 +674,6 @@ def warn_pragma_align_invalid_option : Warning< // - #pragma pack def warn_pragma_pack_invalid_action : Warning< "unknown action for '#pragma pack' - ignored">; -def warn_pragma_pack_invalid_constant : Warning< - "invalid constant for '#pragma pack', expected %0 - ignored">; def warn_pragma_pack_malformed : Warning< "expected integer or identifier in '#pragma pack' - ignored">; // - #pragma unused @@ -592,7 +710,7 @@ def err_seh___finally_block : Error< let CategoryName = "Modules Issue" in { def err_module_expected_ident : Error< - "expected a module name after '__import_module__'">; + "expected a module name after module import">; def err_module_expected_semi : Error< "expected a semicolon name after module name">; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index d60e69b..e553740 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -16,10 +16,38 @@ let CategoryName = "Semantic Issue" in { // Constant expressions def err_expr_not_ice : Error< - "expression is not an integer constant expression">; + "expression is not an %select{integer|integral}0 constant expression">; def ext_expr_not_ice : Extension< - "expression is not integer constant expression " - "(but is allowed as an extension)">; + "expression is not an %select{integer|integral}0 constant expression; " + "folding it to a constant is a GNU extension">, InGroup<GNU>; +def err_typecheck_converted_constant_expression : Error< + "value of type %0 is not implicitly convertible to %1">; +def err_typecheck_converted_constant_expression_disallowed : Error< + "conversion from %0 to %1 is not allowed in a converted constant expression">; +def err_expr_not_cce : Error< + "%select{case value|enumerator value|non-type template argument}0 " + "is not a constant expression">; +def err_cce_narrowing : ExtWarn< + "%select{case value|enumerator value|non-type template argument}0 " + "%select{cannot be narrowed from type %2 to %3|" + "evaluates to %2, which cannot be narrowed to type %3}1">, + InGroup<CXX11Narrowing>, DefaultError; +def err_cce_narrowing_sfinae : Error< + "%select{case value|enumerator value|non-type template argument}0 " + "%select{cannot be narrowed from type %2 to %3|" + "evaluates to %2, which cannot be narrowed to type %3}1">; +def err_ice_not_integral : Error< + "integral constant expression must have integral or unscoped enumeration " + "type, not %0">; +def err_ice_incomplete_type : Error< + "integral constant expression has incomplete class type %0">; +def err_ice_explicit_conversion : Error< + "integral constant expression requires explicit conversion from %0 to %1">; +def note_ice_conversion_here : Note< + "conversion to %select{integral|enumeration}0 type %1 declared here">; +def err_ice_ambiguous_conversion : Error< + "ambiguous conversion from type %0 to an integral or unscoped " + "enumeration type">; // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< @@ -35,8 +63,7 @@ def warn_double_const_requires_fp64 : Warning< "double precision constant requires cl_khr_fp64, casting to single precision">; // C99 variable-length arrays -def ext_vla : Extension< - "variable length arrays are a C99 feature, accepted as an extension">, +def ext_vla : Extension<"variable length arrays are a C99 feature">, InGroup<VLA>; def err_vla_non_pod : Error<"variable length array of non-POD element type %0">; def err_vla_in_sfinae : Error< @@ -63,8 +90,6 @@ def err_variably_modified_new_type : Error< // C99 Designated Initializers def ext_designated_init : Extension< "designated initializers are a C99 feature">; -def ext_designated_init_cxx : Extension< - "designated initializers are a C99 feature, accepted in C++ as an extension">; def err_array_designator_negative : Error< "array designator value '%0' is negative">; def err_array_designator_empty_range : Error< @@ -100,8 +125,6 @@ def ext_flexible_array_init : Extension< "flexible array initialization is a GNU extension">, InGroup<GNU>; // Declarations. -def ext_anon_param_requires_type_specifier : Extension< - "type specifier required for unnamed parameter, defaults to int">; def err_bad_variable_name : Error< "%0 cannot be the name of a variable or data member">; def err_bad_parameter_name : Error< @@ -114,7 +137,20 @@ def warn_unused_variable : Warning<"unused variable %0">, def warn_unused_exception_param : Warning<"unused exception parameter %0">, InGroup<UnusedExceptionParameter>, DefaultIgnore; def warn_decl_in_param_list : Warning< - "declaration of %0 will not be visible outside of this function">; + "declaration of %0 will not be visible outside of this function">, + InGroup<Visibility>; +def warn_redefinition_in_param_list : Warning< + "redefinition of %0 will not be visible outside of this function">, + InGroup<Visibility>; +def warn_empty_parens_are_function_decl : Warning< + "empty parentheses interpreted as a function declaration">, + InGroup<VexingParse>; +def note_empty_parens_function_call : Note< + "change this ',' to a ';' to call %0">; +def note_empty_parens_default_ctor : Note< + "remove parentheses to declare a variable">; +def note_empty_parens_zero_initialize : Note< + "replace parentheses with an initializer to declare a variable">; def warn_unused_function : Warning<"unused function %0">, InGroup<UnusedFunction>, DefaultIgnore; def warn_unused_member_function : Warning<"unused member function %0">, @@ -134,13 +170,16 @@ def warn_parameter_size: Warning< def warn_return_value_size: Warning< "return value of %0 is a large (%1 bytes) pass-by-value object; " "pass it by reference instead ?">, InGroup<LargeByValueCopy>; - +def warn_return_value_udt: Warning< + "%0 has C-linkage specified, but returns user-defined type %1 which is " + "incompatible with C">, InGroup<ReturnTypeCLinkage>; def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, InGroup<ImplicitFunctionDeclare>, DefaultIgnore; def ext_implicit_function_decl : ExtWarn< "implicit declaration of function %0 is invalid in C99">, InGroup<ImplicitFunctionDeclare>; +def note_function_suggestion : Note<"did you mean %0?">; def err_ellipsis_first_arg : Error< "ISO C requires a named argument before '...'">; @@ -192,6 +231,9 @@ def err_using_decl_can_not_refer_to_namespace : Error< "using declaration can not refer to namespace">; def err_using_decl_constructor : Error< "using declaration can not refer to a constructor">; +def warn_cxx98_compat_using_decl_constructor : Warning< + "inherited constructors are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_using_decl_destructor : Error< "using declaration can not refer to a destructor">; def err_using_decl_template_id : Error< @@ -247,7 +289,7 @@ def warn_unreachable : Warning<"will never be executed">, /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< - "implicitly declaring C library function '%0' with type %1">; + "implicitly declaring library function '%0' with type %1">; def note_please_include_header : Note< "please include the header <%0> or explicitly provide a " "declaration for '%1'">; @@ -269,7 +311,8 @@ def warn_redecl_library_builtin : Warning< def err_builtin_definition : Error<"definition of builtin function %0">; def err_types_compatible_p_in_cplusplus : Error< "__builtin_types_compatible_p is not valid in C++">; -def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError; +def warn_builtin_unknown : Warning<"use of unknown builtin %0">, + InGroup<ImplicitFunctionDeclare>, DefaultError; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to dynamic class %2; vtable pointer will be " @@ -292,6 +335,15 @@ def warn_strlcpycat_wrong_size : Warning< InGroup<DiagGroup<"strlcpy-strlcat-size">>; def note_strlcpycat_wrong_size : Note< "change size argument to be the size of the destination">; + +def warn_strncat_large_size : Warning< + "the value of the size argument in 'strncat' is too large, might lead to a " + "buffer overflow">, InGroup<StrncatSize>, DefaultIgnore; +def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears " + "to be size of the source">, InGroup<StrncatSize>, DefaultIgnore; +def note_strncat_wrong_size : Note< + "change the argument to be the free space in the destination buffer minus " + "the terminating null byte">; /// main() // static/inline main() are not errors in C, just in C++. @@ -299,8 +351,12 @@ def warn_static_main : Warning<"'main' should not be declared static">, InGroup<Main>; def err_static_main : Error<"'main' is not allowed to be declared static">; def err_inline_main : Error<"'main' is not allowed to be declared inline">; +def err_constexpr_main : Error< + "'main' is not allowed to be declared constexpr">; def err_main_template_decl : Error<"'main' cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; +def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, + InGroup<MainReturnType>; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, @@ -339,8 +395,14 @@ def warn_pragma_unused_undeclared_var : Warning< "undeclared variable %0 used as an argument for '#pragma unused'">; def warn_pragma_unused_expected_var_arg : Warning< "only variables can be arguments to '#pragma unused'">; -def err_unsupported_pragma_weak : Error< - "using '#pragma weak' to refer to an undeclared identifier is not yet supported">; +def err_pragma_push_visibility_mismatch : Error< + "#pragma visibility push with no matching #pragma visibility pop">; +def note_surrounding_namespace_ends_here : Note< + "surrounding namespace with visibility attribute ends here">; +def err_pragma_pop_visibility_mismatch : Error< + "#pragma visibility pop with no matching #pragma visibility push">; +def note_surrounding_namespace_starts_here : Note< + "surrounding namespace with visibility attribute starts here">; /// Objective-C parser diagnostics def err_duplicate_class_def : Error< @@ -370,12 +432,25 @@ def warn_property_attribute : Warning< def warn_property_types_are_incompatible : Warning< "property type %0 is incompatible with type %1 inherited from %2">; def err_undef_interface : Error<"cannot find interface declaration for %0">; +def err_category_forward_interface : Error< + "cannot define %select{category|class extension}0 for undefined class %1">; def err_class_extension_after_impl : Error< "cannot declare class extension for %0 after class implementation">; def note_implementation_declared : Note< "class implementation is declared here">; def note_class_declared : Note< "class is declared here">; +def note_receiver_is_id : Note< + "receiver is treated with 'id' type for purpose of method lookup">; +def note_suppressed_class_declare : Note< + "class with specified objc_requires_property_definitions attribute is declared here">; +def err_objc_root_class_subclass : Error< + "objc_root_class attribute may only be specified on a root class declaration">; +def warn_objc_root_class_missing : Warning< + "class %0 defined without specifying a base class">, + InGroup<ObjCRootClass>, DefaultIgnore; +def note_objc_needs_superclass : Note< + "add a super class to fix this problem">; def warn_dup_category_def : Warning< "duplicate definition of category %1 on interface %0">; def err_conflicting_super_class : Error<"conflicting super class name %0">; @@ -479,11 +554,13 @@ def warn_strict_multiple_method_decl : Warning< "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore; def warn_accessor_property_type_mismatch : Warning< "type of property %0 does not match type of accessor %1">; -def note_declared_at : Note<"declared here">; -def note_method_declared_at : Note<"method declared here">; +def not_conv_function_declared_at : Note<"type conversion function declared here">; +def note_method_declared_at : Note<"method %0 declared here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; -def err_missing_atend : Error<"'@end' is missing in implementation context">; +def warn_duplicate_method_decl : + Warning<"multiple declarations of method %0 found and ignored">, + InGroup<MethodDuplicate>, DefaultIgnore; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< @@ -495,6 +572,10 @@ def err_objc_property_requires_object : Error< def warn_objc_property_no_assignment_attribute : Warning< "no 'assign', 'retain', or 'copy' attribute is specified - " "'assign' is assumed">; +def warn_objc_isa_use : Warning< + "direct access to objective-c's isa is deprecated " + "in favor of object_setClass() and object_getClass()">, + InGroup<DiagGroup<"deprecated-objc-isa-usage">>; def warn_objc_property_default_assign_on_object : Warning< "default property attribute 'assign' not appropriate for non-gc object">; def warn_property_attr_mismatch : Warning< @@ -505,19 +586,26 @@ def warn_objc_property_copy_missing_on_block : Warning< def warn_objc_property_retain_of_block : Warning< "retain'ed block property does not copy the block " "- use copy attribute instead">, InGroup<ObjCRetainBlockProperty>; +def warn_objc_readonly_property_has_setter : Warning< + "setter cannot be specified for a readonly property">, + InGroup<ObjCReadonlyPropertyHasSetter>; def warn_atomic_property_rule : Warning< "writable atomic property %0 cannot pair a synthesized %select{getter|setter}1 " "with a user defined %select{getter|setter}2">, InGroup<DiagGroup<"atomic-property-with-user-defined-accessor">>; def note_atomic_property_fixup_suggest : Note<"setter and getter must both be " "synthesized, or both be user defined,or the property must be nonatomic">; -def warn_atomic_property_nontrivial_assign_op : Warning< - "atomic property of type %0 synthesizing setter using non-trivial assignment" - " operator">, InGroup<DiagGroup<"objc-property-atomic-setter-synthesis">>; +def err_atomic_property_nontrivial_assign_op : Error< + "atomic property of reference type %0 cannot have non-trivial assignment" + " operator">; def warn_owning_getter_rule : Warning< "property's synthesized getter follows Cocoa naming" " convention for returning 'owned' objects">, InGroup<DiagGroup<"objc-property-matches-cocoa-ownership-rule">>; +def warn_auto_synthesizing_protocol_property :Warning< + "auto property synthesis will not synthesize property" + " declared in a protocol">, + InGroup<DiagGroup<"objc-protocol-property-synthesis">>; def warn_property_getter_owning_mismatch : Warning< "property declared as returning non-retained objects" "; getter returning retained objects">; @@ -531,9 +619,9 @@ def warn_default_atomic_custom_getter_setter : Warning< def err_use_continuation_class : Error< "illegal redeclaration of property in continuation class %0" " (attribute must be 'readwrite', while its primary must be 'readonly')">; -def warn_type_mismatch_continuation_class : Warning< +def err_type_mismatch_continuation_class : Error< "type of property %0 in continuation class does not match " - "property type in primary class">, InGroup<ObjCContinuationPropertyType>; + "property type in primary class">; def err_use_continuation_class_redeclaration_readwrite : Error< "illegal redeclaration of 'readwrite' property in continuation class %0" " (perhaps you intended this to be a 'readwrite' redeclaration of a " @@ -571,6 +659,9 @@ def warn_arc_perform_selector_leaks : Warning< InGroup<DiagGroup<"arc-performSelector-leaks">>; def err_gc_weak_property_strong_type : Error< "weak attribute declared on a __strong type property in GC mode">; +def warn_receiver_is_weak : Warning < + "weak receiver may be unpredictably null in ARC mode">, + InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore; def error_synthesized_ivar_yet_not_supported : Error< "instance variable synthesis not yet supported" @@ -608,12 +699,12 @@ def warn_auto_implicit_atomic_property : Warning< def warn_unimplemented_selector: Warning< "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< - "method in protocol not implemented">, InGroup<Protocol>; + "method %0 in protocol not implemented">, InGroup<Protocol>; // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; -def err_static_assert_failed : Error<"static_assert failed \"%0\"">; +def err_static_assert_failed : Error<"static_assert failed %0">; def warn_inline_namespace_reopened_noninline : Warning< "inline namespace cannot be re-opened as a non-inline namespace">; @@ -625,13 +716,25 @@ def err_unexpected_friend : Error< "friends can only be classes or functions">; def ext_enum_friend : ExtWarn< "enumeration type %0 cannot be a friend">; +def warn_cxx98_compat_enum_friend : Warning< + "befriending enumeration type %0 is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def ext_nonclass_type_friend : ExtWarn< "non-class friend type %0 is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_nonclass_type_friend : Warning< + "non-class friend type %0 is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_friend_is_member : Error< "friends cannot be members of the declaring class">; +def warn_cxx98_compat_friend_is_member : Warning< + "friend declaration naming a member of the declaring class is incompatible " + "with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def ext_unelaborated_friend_type : ExtWarn< - "specify '%select{struct|union|class|enum}0' to befriend %1; accepted " - "as a C++11 extension">, InGroup<CXX11>; + "unelaborated friend declaration is a C++11 extension; specify " + "'%select{struct|union|class|enum}0' to befriend %1">, InGroup<CXX11>; +def warn_cxx98_compat_unelaborated_friend_type : Warning< + "befriending %1 without '%select{struct|union|class|enum}0' keyword is " + "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; def err_introducing_special_friend : Error< @@ -681,6 +784,10 @@ def warn_weak_vtable : Warning< "%0 has no out-of-line virtual method definitions; its vtable will be " "emitted in every translation unit">, InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore; +def warn_weak_template_vtable : Warning< + "explicit template instantiation %0 will emit a vtable in every " + "translation unit">, + InGroup<DiagGroup<"weak-template-vtables">>, DefaultIgnore; def ext_using_undefined_std : ExtWarn< "using directive refers to implicitly-defined namespace 'std'">; @@ -720,9 +827,9 @@ def err_class_redeclared_with_different_access : Error< "%0 redeclared with '%1' access">; def err_access : Error< "%1 is a %select{private|protected}0 member of %3">, AccessControl; -def war_ms_using_declaration_inaccessible : ExtWarn< - "using declaration refers to inaccessible member '%0', which refers " - "to accessible member '%1', accepted for Microsoft compatibility">, +def ext_ms_using_declaration_inaccessible : ExtWarn< + "using declaration referring to inaccessible member '%0' (which refers " + "to accessible member '%1') is a Microsoft compatibility extension">, AccessControl, InGroup<Microsoft>; def err_access_ctor : Error< "calling a %select{private|protected}0 constructor of class %2">, @@ -744,9 +851,6 @@ def err_access_field_ctor : Error< "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">, AccessControl; -def err_access_ctor_field : - Error<"field of type %1 has %select{private|protected}2 constructor">, - AccessControl; def err_access_dtor : Error< "calling a %select{private|protected}1 destructor of class %0">, AccessControl; @@ -769,36 +873,27 @@ def err_access_dtor_field : def err_access_dtor_var : Error<"variable of type %1 has %select{private|protected}2 destructor">, AccessControl; -def err_access_assign_field : - Error<"field of type %1 has %select{private|protected}2 copy assignment" - " operator">, - AccessControl; -def err_access_assign_base : - Error<"base class %0 has %select{private|protected}1 copy assignment" - " operator">, - AccessControl; -def err_access_copy_field : - Error<"field of type %1 has %select{private|protected}2 copy constructor">, - AccessControl; -def err_access_copy_base : - Error<"base class %0 has %select{private|protected}1 copy constructor">, - AccessControl; def err_access_dtor_ivar : Error<"instance variable of type %0 has %select{private|protected}1 " "destructor">, AccessControl; def note_previous_access_declaration : Note< "previously declared '%1' here">; -def err_access_outside_class : Error< - "access to %select{private|protected}0 member outside any class context">, - AccessControl; def note_access_natural : Note< "%select{|implicitly }1declared %select{private|protected}0 here">; def note_access_constrained_by_path : Note< "constrained by %select{|implicitly }1%select{private|protected}0" " inheritance here">; -def note_access_protected_restricted : Note< - "object type %select{|%1 }0must derive from context type %2">; +def note_access_protected_restricted_noobject : Note< + "must name member using the type of the current context %0">; +def note_access_protected_restricted_ctordtor : Note< + "protected %select{constructor|destructor}0 can only be used to " + "%select{construct|destroy}0 a base class subobject">; +def note_access_protected_restricted_object : Note< + "can only access this member on an object of type %0">; +def warn_cxx98_compat_sfinae_access_control : Warning< + "substitution failure due to access control is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore, NoSFINAE; // C++ name lookup def err_incomplete_nested_name_spec : Error< @@ -821,6 +916,9 @@ 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">; +def warn_cxx98_compat_enum_nested_name_spec : Warning< + "enumeration type in nested name specifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; // C++ class members def err_storageclass_invalid_for_member : Error< @@ -885,6 +983,11 @@ def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " "%select{constructor|copy constructor|move constructor|copy assignment " "operator|move assignment operator|destructor}2">; +def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< + "%select{anonymous struct|union}0 member %1 with a non-trivial " + "%select{constructor|copy constructor|move constructor|copy assignment " + "operator|move assignment operator|destructor}2 is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; def note_nontrivial_has_nontrivial : Note< @@ -895,8 +998,13 @@ def note_nontrivial_user_defined : Note< "because type %0 has a user-declared %select{constructor|copy constructor|" "move constructor|copy assignment operator|move assignment operator|" "destructor}1">; -def err_static_data_member_not_allowed_in_union_or_anon_struct : Error< - "static data member %0 not allowed in %select{anonymous struct|union}1">; +def err_static_data_member_not_allowed_in_anon_struct : Error< + "static data member %0 not allowed in anonymous struct">; +def ext_static_data_member_in_union : ExtWarn< + "static data member %0 in union is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_static_data_member_in_union : Warning< + "static data member %0 in union is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_union_member_of_reference_type : Error< "union member %0 has reference type %1">; def ext_anonymous_struct_union_qualified : Extension< @@ -983,17 +1091,22 @@ def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element}0 of type %1 with an " - "%select{rvalue|lvalue}2 of type %3">; + "%select{rvalue|lvalue}2 of type %3" + "%select{|: different classes (%5 vs %6)" + "|: different number of parameters (%5 vs %6)" + "|: type mismatch at %ordinal5 parameter (%6 vs %7)" + "|: different return type (%5 vs %6)" + "|: different qualifiers (" + "%select{none|const|restrict|const and restrict|volatile|const and volatile|" + "volatile and restrict|const, volatile, and restrict}5 vs " + "%select{none|const|restrict|const and restrict|volatile|const and volatile|" + "volatile and restrict|const, volatile, and restrict}6)}4">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind " "to lvalue of type %1">; -def err_invalid_initialization : Error< -"invalid initialization of reference of type %0 from expression of type %1">; -def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue " - "due to multiple conversion functions">; -def err_not_reference_to_const_init : Error< - "%select{non-const|volatile}0 lvalue reference to type %1 cannot be " - "initialized with a %select{value|temporary}2 of type %3">; +def err_lvalue_reference_bind_to_initlist : Error< + "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to an " + "initializer list temporary">; def err_lvalue_reference_bind_to_temporary : Error< "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " "temporary of type %2">; @@ -1015,17 +1128,12 @@ def err_member_function_call_bad_cvr : Error<"member function %0 not viable: " "%select{const|restrict|const or restrict|volatile|const or volatile|" "volatile or restrict|const, volatile, or restrict}2">; -def err_reference_init_drops_quals : Error< - "initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops " - "qualifiers">; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to bit-field %1">; def err_reference_bind_to_vector_element : Error< "%select{non-const|volatile}0 reference cannot bind to vector element">; def err_reference_var_requires_init : Error< "declaration of reference variable %0 requires an initializer">; -def err_const_var_requires_init : Error< - "declaration of const variable '%0' requires an initializer">; def err_reference_without_init : Error< "reference to type %0 requires an initializer">; def err_reference_has_multiple_inits : Error< @@ -1055,6 +1163,11 @@ def warn_uninit_var_captured_by_block : Warning< def warn_maybe_uninit_var_captured_by_block : Warning< "variable %0 may be uninitialized when captured by block">, InGroup<UninitializedMaybe>, DefaultIgnore; +def warn_uninit_byref_blockvar_captured_by_block : Warning< + "block pointer variable %0 is uninitialized when captured by block">, + InGroup<Uninitialized>, DefaultIgnore; +def note_block_var_fixit_add_initialization : Note< + "maybe you meant to use __block %0">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; @@ -1063,32 +1176,47 @@ def err_temp_copy_no_viable : Error< "no viable constructor %select{copying variable|copying parameter|" "returning object|throwing object|copying member subobject|copying array " "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element}0 of type %1">; + "initializing vector element|capturing value}0 of type %1">; def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn< "no viable constructor %select{copying variable|copying parameter|" "returning object|throwing object|copying member subobject|copying array " "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element}0 of type %1; C++98 requires a copy " + "initializing vector element|capturing value}0 of type %1; C++98 requires a copy " "constructor when binding a reference to a temporary">, InGroup<BindToTemporaryCopy>; def err_temp_copy_ambiguous : Error< "ambiguous constructor call when %select{copying variable|copying " "parameter|returning object|throwing object|copying member subobject|copying " "array element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element}0 of type %1">; + "initializing vector element|capturing value}0 of type %1">; def err_temp_copy_deleted : Error< "%select{copying variable|copying parameter|returning object|throwing " "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element}0 " - "of type %1 invokes deleted constructor">; + "copying temporary|initializing base subobject|initializing vector element|" + "capturing value}0 of type %1 invokes deleted constructor">; def err_temp_copy_incomplete : Error< "copying a temporary object of incomplete type %0">; +def warn_cxx98_compat_temp_copy : Warning< + "%select{copying variable|copying parameter|returning object|throwing " + "object|copying member subobject|copying array element|allocating object|" + "copying temporary|initializing base subobject|initializing vector element}1 " + "of type %2 when binding a reference to a temporary would %select{invoke " + "an inaccessible constructor|find no viable constructor|find ambiguous " + "constructors|invoke a deleted constructor}0 in C++98">, + InGroup<CXX98CompatBindToTemporaryCopy>, DefaultIgnore; +def err_selected_explicit_constructor : Error< + "chosen constructor is explicit in copy-initialization">; +def note_constructor_declared_here : Note< + "constructor declared here">; // C++11 decltype -def err_cannot_determine_declared_type_of_overloaded_function : Error< - "cannot determine the type of an overloaded function">; +def err_decltype_in_declarator : Error< + "'decltype' cannot be used to name a declaration">; // C++11 auto +def warn_cxx98_compat_auto_type_specifier : Warning< + "'auto' type specifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_auto_variable_cannot_appear_in_own_initializer : Error< "variable %0 declared with 'auto' type cannot appear in its own initializer">; def err_illegal_decl_array_of_auto : Error< @@ -1104,6 +1232,10 @@ def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; +def err_auto_new_requires_parens : Error< + "new expression for type %0 cannot use list-initialization">; +def err_auto_var_init_no_expression : Error< + "initializer for variable %0 with type %1 is empty">; def err_auto_var_init_multiple_expressions : Error< "initializer for variable %0 with type %1 contains multiple expressions">; def err_auto_new_ctor_multiple_expressions : Error< @@ -1116,10 +1248,21 @@ def err_trailing_return_in_parens : Error< "trailing return type may not be nested within parentheses">; def err_auto_var_deduction_failure : Error< "variable %0 with type %1 has incompatible initializer of type %2">; +def err_auto_var_deduction_failure_from_init_list : Error< + "cannot deduce actual type for variable %0 with type %1 from initializer list">; def err_auto_new_deduction_failure : Error< "new expression for type %0 has incompatible constructor argument of type %1">; def err_auto_different_deductions : Error< "'auto' deduced as %0 in declaration of %1 and deduced as %2 in declaration of %3">; +def err_implied_std_initializer_list_not_found : Error< + "cannot deduce type of initializer list because std::initializer_list was " + "not found; include <initializer_list>">; +def err_malformed_std_initializer_list : Error< + "std::initializer_list must be a class template with a single type parameter">; +def warn_dangling_std_initializer_list : Warning< + "array backing the initializer list will be destroyed at the end of " + "%select{the full-expression|the constructor}0">, + InGroup<DiagGroup<"dangling-initializer-list">>; // C++11 override control def override_keyword_only_allowed_on_virtual_member_functions : Error< @@ -1132,11 +1275,9 @@ def err_class_marked_final_used_as_base : Error< // C++11 attributes def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; -// C++11 [[final]] +// C++11 final def err_final_function_overridden : Error< "declaration of %0 overrides a 'final' function">; -def err_final_base : Error< - "derivation from 'final' %0">; // C++11 scoped enumerations def err_enum_invalid_underlying : Error< @@ -1154,14 +1295,18 @@ def err_enum_redeclare_fixed_mismatch : Error< "enumeration previously declared with %select{non|}0fixed underlying type">; def err_enum_redeclare_scoped_mismatch : Error< "enumeration previously declared as %select{un|}0scoped">; +def err_enum_class_reference : Error< + "reference to %select{|scoped }0enumeration must use 'enum' " + "not 'enum class'">; def err_only_enums_have_underlying_types : Error< "only enumeration types have underlying types">; -def err_incomplete_type_no_underlying_type : Error< - "an incomplete enumeration type has no underlying type yet">; // C++11 delegating constructors -def err_delegation_0x_only : Error< +def err_delegating_ctor : Error< "delegating constructors are permitted only in C++11">; +def warn_cxx98_compat_delegating_ctor : Warning< + "delegating constructors are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_delegating_initializer_alone : Error< "an initializer for a delegating constructor must appear alone">; def warn_delegating_ctor_cycle : Warning< @@ -1171,8 +1316,6 @@ def note_it_delegates_to : Note< "it delegates to">, InGroup<DelegatingCtorCycles>; def note_which_delegates_to : Note< "which delegates to">, InGroup<DelegatingCtorCycles>; -def err_delegating_codegen_not_implemented : Error< - "code generation for delegating constructors not implemented">; // C++11 range-based for loop def err_for_range_decl_must_be_var : Error< @@ -1197,6 +1340,9 @@ def note_for_range_begin_end : Note< "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; // C++11 constexpr +def warn_cxx98_compat_constexpr : Warning< + "'constexpr' specifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " "cannot be constexpr">; @@ -1207,37 +1353,27 @@ def err_constexpr_no_declarators : Error< "constexpr can only be used in variable and function declarations">; def err_invalid_constexpr_var_decl : Error< "constexpr variable declaration must be a definition">; -def err_constexpr_var_requires_init : Error< - "declaration of constexpr variable %0 requires an initializer">; +def err_constexpr_static_mem_var_requires_init : Error< + "declaration of constexpr static data member %0 requires an initializer">; +def err_constexpr_var_non_literal : Error< + "constexpr variable cannot have non-literal type %0">; def err_constexpr_var_requires_const_init : Error< "constexpr variable %0 must be initialized by a constant expression">; def err_constexpr_redecl_mismatch : Error< "%select{non-constexpr declaration of %0 follows constexpr declaration" "|constexpr declaration of %0 follows non-constexpr declaration}1">; -def note_constexpr_redecl_mismatch : Note< - "previous declaration was %select{not |}0marked constexpr">; def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; -def note_constexpr_tmpl_virtual : Note<"function template instantiation is not " - "constexpr because it is virtual">; -def err_constexpr_virtual_base : Error<"constexpr constructor not allowed in " - "%select{class|struct}0 with virtual base %plural{1:class|:classes}1">; -def note_constexpr_tmpl_virtual_base : Note<"constructor template instantiation is " - "not constexpr because %select{class|struct}0 has virtual base " - "%plural{1:class|:classes}1">; +def err_constexpr_virtual_base : Error< + "constexpr %select{member function|constructor}0 not allowed in " + "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">; def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual " "base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; def err_constexpr_non_literal_return : Error< "constexpr function's return type %0 is not a literal type">; -def note_constexpr_tmpl_non_literal_return : Note< - "function template instantiation is not constexpr because return type %0 is " - "not a literal type">; def err_constexpr_non_literal_param : Error< "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is " "not a literal type">; -def note_constexpr_tmpl_non_literal_param : Note< - "%select{function|constructor}1 template instantiation is not constexpr " - "because %ordinal0 parameter type %2 is not a literal type">; def err_constexpr_body_invalid_stmt : Error< "statement not allowed in constexpr %select{function|constructor}0">; def err_constexpr_type_definition : Error< @@ -1247,6 +1383,9 @@ def err_constexpr_vla : Error< "%select{function|constructor}1">; def err_constexpr_var_declaration : Error< "variables cannot be declared in a constexpr %select{function|constructor}0">; +def err_constexpr_function_never_constant_expr : ExtWarn< + "constexpr %select{function|constructor}0 never produces a " + "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; def err_constexpr_body_multiple_return : Error< @@ -1269,21 +1408,24 @@ def note_non_literal_no_constexpr_ctors : Note< def note_non_literal_base_class : Note< "%0 is not literal because it has base class %1 of non-literal type">; def note_non_literal_field : Note< - "%0 is not literal because it has data member %1 of non-literal type %2">; + "%0 is not literal because it has data member %1 of " + "%select{non-literal|volatile}3 type %2">; def note_non_literal_user_provided_dtor : Note< "%0 is not literal because it has a user-provided destructor">; def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; -def note_non_literal_mutable_field : Note< - "%0 is not literal because it has a mutable data member">; + +// C++11 char16_t/char32_t +def warn_cxx98_compat_unicode_type : Warning< + "'%0' type specifier is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< "Objective-C declarations may only appear in global scope">; +// Attributes def err_nsobject_attribute : Error< "__attribute ((NSObject)) is for pointer types only">; - -// Attributes def err_attribute_can_be_applied_only_to_symbol_declaration : Error< "%0 attribute can be applied only to symbol declaration">; def err_attributes_are_not_compatible : Error< @@ -1293,6 +1435,9 @@ def err_attribute_wrong_number_arguments : Error< ":requires exactly %0 arguments}0">; def err_attribute_too_many_arguments : Error< "attribute takes no more than %0 argument%s0">; +def err_suppress_autosynthesis : Error< + "objc_requires_property_definitions attribute may only be specified on a class" + "to a class declaration">; def err_attribute_too_few_arguments : Error< "attribute takes at least %0 argument%s0">; def err_attribute_missing_parameter_name : Error< @@ -1347,8 +1492,6 @@ def err_typecheck_vector_not_convertable : Error< "can't convert between vector values of different size (%0 and %1)">; def err_typecheck_ext_vector_not_typedef : Error< "ext_vector_type only applies to types, not variables">; -def err_unsupported_vector_size : Error< - "unsupported type %0 for vector_size attribute, please use on typedef">; def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< @@ -1367,12 +1510,46 @@ def err_as_qualified_auto_decl : Error< "automatic variable qualified with an address space">; def err_arg_with_address_space : Error< "parameter may not be qualified with an address space">; -def err_attr_objc_ownership_bad_type : Error< - "the type %0 cannot be retained">; def err_attr_objc_ownership_redundant : Error< - "the type %0 already has retainment attributes set on it">; + "the type %0 is already explicitly ownership-qualified">; def err_attribute_not_string : Error< "argument to %0 attribute was not a string literal">; +def err_undeclared_nsnumber : Error< + "NSNumber must be available to use Objective-C literals">; +def err_invalid_nsnumber_type : Error< + "%0 is not a valid literal type for NSNumber">; +def err_undeclared_nsarray : Error< + "NSArray must be available to use Objective-C array literals">; +def err_undeclared_nsdictionary : Error< + "NSDictionary must be available to use Objective-C dictionary " + "literals">; +def err_undeclared_arraywithobjects : Error< + "declaration of %0 is missing in NSArray class">; +def err_undeclared_dictwithobjects : Error< + "declaration of %0 is missing in NSDictionary class">; +def err_undeclared_nsnumber_method : Error< + "declaration of %0 is missing in NSNumber class">; +def err_objc_literal_method_sig : Error< + "literal construction method %0 has incompatible signature">; +def note_objc_literal_method_param : Note< + "%select{first|second|third}0 parameter has unexpected type %1 " + "(should be %2)">; +def note_objc_literal_method_return : Note< + "method returns unexpected type %0 (should be an object type)">; +def err_invalid_collection_element : Error< + "collection element of type %0 is not an Objective-C object">; +def err_box_literal_collection : Error< + "%select{string|character|boolean|numeric}0 literal must be prefixed by '@' " + "in a collection">; + +let CategoryName = "Cocoa API Issue" in { +def warn_objc_redundant_literal_use : Warning< + "using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>; +} + +def warn_bool_for_boolean_literal : Warning< + "BOOL of type %0 is non-intergal and unsuitable for a " + "boolean literal - ignored">, InGroup<DiagGroup<"numeric-literals">>; def err_only_annotate_after_access_spec : Error< "access specifier can only have annotation attributes">; def err_attribute_section_invalid_for_target : Error< @@ -1386,6 +1563,8 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< def warn_attribute_ignored : Warning<"%0 attribute ignored">; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; +def warn_declspec_attribute_ignored : Warning< + "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; def warn_attribute_void_function_method : Warning< @@ -1395,6 +1574,9 @@ def warn_attribute_weak_on_field : Warning< "__weak attribute cannot be specified on a field declaration">; def warn_gc_attribute_weak_on_local : Warning< "Objective-C GC does not allow weak variables on the stack">; +def warn_nsobject_attribute : Warning< + "__attribute ((NSObject)) may be put on a typedef only, " + "attribute is ignored">, InGroup<NSobjectAttribute>; def warn_attribute_weak_on_local : Warning< "__weak attribute cannot be specified on an automatic variable">; def warn_weak_identifier_undeclared : Warning< @@ -1414,16 +1596,15 @@ def err_alias_not_supported_on_darwin : Error < def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "parameters and methods|functions, methods and blocks|" - "classes and virtual methods|functions, methods, and parameters|" - "classes|virtual methods|class members|variables|methods|" - "variables, functions and labels|fields and global variables}1">; + "functions, methods and blocks|functions, methods, and parameters|" + "classes|variables|methods|variables, functions and labels|" + "fields and global variables|structs}1">; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" - "parameters and methods|functions, methods and blocks|" - "classes and virtual methods|functions, methods, and parameters|" - "classes|virtual methods|class members|variables|methods|structs}1">; + "functions, methods and blocks|functions, methods, and parameters|" + "classes|variables|methods|variables, functions and labels|" + "fields and global variables|structs}1">; def warn_function_attribute_wrong_type : Warning< "'%0' only applies to function types; type here is %1">; def warn_pointer_attribute_wrong_type : Warning< @@ -1455,8 +1636,6 @@ def err_objc_precise_lifetime_bad_type : Error< def warn_objc_precise_lifetime_meaningless : Error< "objc_precise_lifetime is not meaningful for " "%select{__unsafe_unretained|__autoreleasing}0 objects">; -def warn_label_attribute_not_unused : Warning< - "The only valid attribute for labels is 'unused'">; def err_invalid_pcs : Error<"Invalid PCS type">; def err_attribute_can_be_applied_only_to_value_decl : Error< "%0 attribute can only be applied to value declarations">; @@ -1479,12 +1658,18 @@ def err_attribute_argument_out_of_range : Error< "%plural{0:no parameters to index into|" "1:can only be 1, since there is one parameter|" ":must be between 1 and %2}2">; -def err_attribute_argument_not_lockable : Error< +def warn_attribute_argument_not_lockable : Warning< "%0 attribute requires arguments whose type is annotated " - "with 'lockable' attribute">; -def err_attribute_decl_not_lockable : Error< + "with 'lockable' attribute; type here is '%1'">, + InGroup<ThreadSafety>, DefaultIgnore; +def warn_attribute_decl_not_lockable : Warning< "%0 attribute can only be applied in a context annotated " - "with 'lockable' attribute">; + "with 'lockable' attribute">, + InGroup<ThreadSafety>, DefaultIgnore; +def warn_attribute_argument_not_class : Warning< + "%0 attribute requires arguments that are class type or point to" + " class type; type here is '%1'">, + InGroup<ThreadSafety>, DefaultIgnore; def warn_unlock_but_no_lock : Warning< "unlocking '%0' that was not locked">, InGroup<ThreadSafety>, DefaultIgnore; @@ -1495,12 +1680,13 @@ def warn_no_unlock : Warning< "mutex '%0' is still locked at the end of function">, InGroup<ThreadSafety>, DefaultIgnore; // FIXME: improve the error message about locks not in scope -def warn_lock_at_end_of_scope : Warning< - "mutex '%0' is still locked at the end of its scope">, +def warn_lock_some_predecessors : Warning< + "mutex '%0' is not locked on every path through here">, InGroup<ThreadSafety>, DefaultIgnore; def warn_expecting_lock_held_on_loop : Warning< "expecting mutex '%0' to be locked at start of each loop">, InGroup<ThreadSafety>, DefaultIgnore; +def note_locked_here : Note<"mutex acquired here">; def warn_lock_exclusive_and_shared : Warning< "mutex '%0' is locked exclusively and shared in the same scope">, InGroup<ThreadSafety>, DefaultIgnore; @@ -1530,7 +1716,7 @@ def warn_fun_excludes_mutex : Warning< "cannot call function '%0' while mutex '%1' is locked">, InGroup<ThreadSafety>, DefaultIgnore; def warn_cannot_resolve_lock : Warning< - "cannot resolve lock expression to a specific lockable object">, + "cannot resolve lock expression">, InGroup<ThreadSafety>, DefaultIgnore; @@ -1548,10 +1734,10 @@ def warn_impcast_float_integer : Warning< InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, - InGroup<DiagGroup<"sign-conversion">>, DefaultIgnore; + InGroup<SignConversion>, DefaultIgnore; def warn_impcast_integer_sign_conditional : Warning< "operand of ? changes signedness: %0 to %1">, - InGroup<DiagGroup<"sign-conversion">>, DefaultIgnore; + InGroup<SignConversion>, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; @@ -1560,26 +1746,33 @@ def warn_impcast_integer_64_32 : Warning< InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; def warn_impcast_integer_precision_constant : Warning< "implicit conversion from %2 to %3 changes value from %0 to %1">, - InGroup<DiagGroup<"constant-conversion">>; + InGroup<ConstantConversion>; def warn_impcast_bitfield_precision_constant : Warning< "implicit truncation from %2 to bitfield changes value from %0 to %1">, - InGroup<DiagGroup<"constant-conversion">>; + InGroup<ConstantConversion>; def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%0 to %1">, - InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore; + InGroup<LiteralConversion>; def warn_impcast_string_literal_to_bool : Warning< "implicit conversion turns string literal into bool: %0 to %1">, - InGroup<DiagGroup<"string-conversion">>, DefaultIgnore; + InGroup<StringConversion>, DefaultIgnore; def warn_impcast_different_enum_types : Warning< "implicit conversion from enumeration type %0 to different enumeration type " "%1">, InGroup<DiagGroup<"conversion">>; def warn_impcast_bool_to_null_pointer : Warning< "initialization of pointer of type %0 to null from a constant boolean " - "expression">, InGroup<BoolConversions>; + "expression">, InGroup<BoolConversion>; def warn_impcast_null_pointer_to_integer : Warning< - "implicit conversion of NULL constant to integer">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + "implicit conversion of NULL constant to %0">, + InGroup<NullConversion>; +def warn_impcast_function_to_bool : Warning< + "address of function %q0 will always evaluate to 'true'">, + InGroup<BoolConversion>; +def note_function_to_bool_silence : Note< + "prefix with the address-of operator to silence this warning">; +def note_function_to_bool_call : Note< + "suffix with parentheses to turn this into a function call">; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, @@ -1605,6 +1798,9 @@ def warn_transparent_union_attribute_zero_fields : Warning< def warn_attribute_type_not_supported : Warning< "'%0' attribute argument not supported: %1">; def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">; +def warn_attribute_protected_visibility : + Warning<"target does not support 'protected' visibility; using 'default'">, + InGroup<DiagGroup<"unsupported-visibility">>; def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; def err_mode_not_primitive : Error< @@ -1617,9 +1813,6 @@ def warn_attribute_nonnull_no_pointers : Warning< "'nonnull' attribute applied to function with no pointer arguments">; def warn_attribute_malloc_pointer_only : Warning< "'malloc' attribute only applies to functions returning a pointer type">; -def warn_transparent_union_nonpointer : Warning< - "'transparent_union' attribute support incomplete; only supported for " - "pointer unions">; def warn_attribute_sentinel_named_arguments : Warning< "'sentinel' attribute requires named arguments">; def warn_attribute_sentinel_not_variadic : Warning< @@ -1650,9 +1843,10 @@ def warn_attribute_ibaction: Warning< "ibaction attribute can only be applied to Objective-C instance methods">; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; -def err_iboutlet_object_type : Error< +def warn_iboutlet_object_type : Warning< "%select{ivar|property}2 with %0 attribute must " - "be an object type (invalid %1)">; + "be an object type (invalid %1)">, + InGroup<DiagGroup<"invalid-iboutlet">>; def err_attribute_overloadable_not_function : Error< "'overloadable' attribute can only be applied to a function">; def err_attribute_overloadable_missing : Error< @@ -1713,8 +1907,6 @@ def err_uninitialized_member_for_assign : Error< "cannot define the implicit default assignment operator for %0, because " "non-static %select{reference|const}1 member %2 can't use default " "assignment operator">; -def note_first_required_here : Note< - "synthesized method is first required here">; def err_uninitialized_member_in_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{reference|const}2 member %3">; @@ -1733,7 +1925,8 @@ def note_default_argument_declared_here : Note< def ext_param_promoted_not_compatible_with_prototype : ExtWarn< "promoted type %0 of K&R function parameter is not compatible with the " - "parameter type %1 declared in a previous prototype">; + "parameter type %1 declared in a previous prototype">, + InGroup<KNRPromotedParameter>; // C++ Overloading Semantic Analysis. @@ -1766,7 +1959,16 @@ def note_ovl_candidate : Note<"candidate " "is the implicit move constructor|" "is the implicit copy assignment operator|" "is the implicit move assignment operator|" - "is an inherited constructor}0%1">; + "is an inherited constructor}0%1" + "%select{| has different class (expected %3 but has %4)" + "| has different number of parameters (expected %3 but has %4)" + "| has type mismatch at %ordinal3 parameter (expected %4 but has %5)" + "| has different return type (%3 expected but has %4)" + "| has different qualifiers (expected " + "%select{none|const|restrict|const and restrict|volatile|const and volatile" + "|volatile and restrict|const, volatile, and restrict}3 but found " + "%select{none|const|restrict|const and restrict|volatile|const and volatile" + "|volatile and restrict|const, volatile, and restrict}4)}2">; def note_ovl_candidate_inherited_constructor : Note<"inherited from here">; def note_ovl_candidate_bad_deduction : Note< @@ -1811,8 +2013,9 @@ def note_ovl_candidate_deleted : Note< "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" - "constructor (inherited)}0%1 " - "has been explicitly %select{made unavailable|deleted}2">; + "constructor (inherited)}0%1 has been " + "%select{explicitly made unavailable|explicitly deleted|" + "implicitly deleted}2">; // Giving the index of the bad argument really clutters this message, and // it's relatively unimportant because 1) it's generally obvious which @@ -1979,6 +2182,10 @@ def err_ref_init_ambiguous : Error< "reference initialization of type %0 with initializer of type %1 is ambiguous">; def err_ovl_deleted_init : Error< "call to %select{unavailable|deleted}0 constructor of %1">; +def err_ovl_deleted_special_init : Error< + "call to implicitly-deleted %select{default constructor|copy constructor|" + "move constructor|copy assignment operator|move assignment operator|" + "destructor|function}0 of %1">; def err_ovl_ambiguous_oper_unary : Error< "use of overloaded operator '%0' is ambiguous (operand type %1)">; def err_ovl_ambiguous_oper_binary : Error< @@ -1986,6 +2193,10 @@ def err_ovl_ambiguous_oper_binary : Error< def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def err_ovl_deleted_oper : Error< "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; +def err_ovl_deleted_special_oper : Error< + "overload resolution selected implicitly-deleted %select{default constructor|" + "copy constructor|move constructor|copy assignment operator|move assignment " + "operator|destructor|'%1'}0%2">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : @@ -2017,7 +2228,13 @@ def err_addr_ovl_not_func_ptrref : Error< "address of overloaded function %0 cannot be converted to type %1">; def err_addr_ovl_no_qualifier : Error< "can't form member pointer of type %0 without '&' and class name">; - + +// C++11 Literal Operators +def err_ovl_no_viable_literal_operator : Error< + "no matching literal operator for call to %0" + "%select{| with argument of type %2| with arguments of types %2 and %3}1" + "%select{| or 'const char *', and no matching literal operator template}4">; + // C++ Template Declarations def err_template_param_shadow : Error< "declaration of %0 shadows template parameter">; @@ -2063,6 +2280,9 @@ def err_template_param_default_arg_missing : Error< def ext_template_parameter_default_in_function_template : ExtWarn< "default template arguments for a function template are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_template_parameter_default_in_function_template : Warning< + "default template arguments for a function template are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_template_parameter_default_template_member : Error< "cannot add a default template argument to the definition of a member of a " "class template">; @@ -2103,6 +2323,12 @@ def ext_template_arg_local_type : ExtWarn< "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>; def ext_template_arg_unnamed_type : ExtWarn< "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>; +def warn_cxx98_compat_template_arg_local_type : Warning< + "local type %0 as template argument is incompatible with C++98">, + InGroup<CXX98CompatLocalTypeTemplateArgs>, DefaultIgnore; +def warn_cxx98_compat_template_arg_unnamed_type : Warning< + "unnamed type as template argument is incompatible with C++98">, + InGroup<CXX98CompatUnnamedTypeTemplateArgs>, DefaultIgnore; def note_template_unnamed_type_here : Note< "unnamed type used in template argument was declared here">; def err_template_arg_overload_type : Error< @@ -2121,6 +2347,13 @@ def err_template_arg_not_integral_or_enumeral : Error< def err_template_arg_not_ice : Error< "non-type template argument of type %0 is not an integral constant " "expression">; +def err_template_arg_not_address_constant : Error< + "non-type template argument of type %0 is not a constant expression">; +def err_template_arg_untyped_null_constant : Error< + "null non-type template argument must be cast to template parameter type %0">; +def err_template_arg_wrongtype_null_constant : Error< + "null non-type template argument of type %0 does not match template parameter " + "of type %1">; def err_deduced_non_type_template_arg_type_mismatch : Error< "deduced non-type template argument does not have the same type as the " "its corresponding template parameter (%0 vs %1)">; @@ -2156,20 +2389,31 @@ def err_template_arg_field : Error< "non-type template argument refers to non-static data member %0">; def err_template_arg_method : Error< "non-type template argument refers to non-static member function %0">; -def err_template_arg_function_not_extern : Error< - "non-template argument refers to function %0 with internal linkage">; -def err_template_arg_object_not_extern : Error< - "non-template argument refers to object %0 that does not have external " - "linkage">; +def err_template_arg_object_no_linkage : Error< + "non-type template argument refers to %select{function|object}0 %1 that " + "does not have linkage">; +def warn_cxx98_compat_template_arg_object_internal : Warning< + "non-type template argument referring to %select{function|object}0 %1 with " + "internal linkage is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def ext_template_arg_object_internal : ExtWarn< + "non-type template argument referring to %select{function|object}0 %1 with " + "internal linkage is a C++11 extension">, InGroup<CXX11>; +def err_template_arg_thread_local : Error< + "non-type template argument refers to thread-local object">; def note_template_arg_internal_object : Note< - "non-template argument refers to %select{function|object}0 here">; -def note_template_arg_refers_here : Note<"non-template argument refers here">; + "non-type template argument refers to %select{function|object}0 here">; +def note_template_arg_refers_here : Note< + "non-type template argument refers here">; def err_template_arg_not_object_or_func : Error< "non-type template argument does not refer to an object or function">; def err_template_arg_not_pointer_to_member_form : Error< "non-type template argument is not a pointer to member constant">; def ext_template_arg_extra_parens : ExtWarn< "address non-type template argument cannot be surrounded by parentheses">; +def warn_cxx98_compat_template_arg_extra_parens : Warning< + "redundant parentheses surrounding address non-type template argument are " + "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_pointer_to_member_type : Error< "invalid use of pointer to member type after %select{.*|->*}0">; def err_pointer_to_member_call_drops_quals : Error< @@ -2181,7 +2425,8 @@ def err_pointer_to_member_oper_value_classify: Error< // C++ template specialization def err_template_spec_unknown_kind : Error< "can only provide an explicit specialization for a class template, function " - "template, or a member function, static data member, or member class of a " + "template, or a member function, static data member, " + "%select{or member class|member class, or member enumeration}0 of a " "class template">; def note_specialized_entity : Note< "explicitly specialized declaration is here">; @@ -2193,30 +2438,30 @@ def err_template_spec_decl_friend : Error< "cannot declare an explicit specialization in a friend">; def err_template_spec_decl_out_of_scope_global : Error< "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 must " - "originally be declared in the global scope">; -def ext_template_spec_decl_out_of_scope_global : ExtWarn< - "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 must " - "originally be declared in the global scope; accepted as a C++11 extension">, - InGroup<CXX11>; + "function|static data member|member class|member enumeration}0 " + "specialization of %1 must originally be declared in the global scope">; def err_template_spec_decl_out_of_scope : Error< "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 must " - "originally be declared in namespace %2">; + "function|static data member|member class|member enumeration}0 " + "specialization of %1 must originally be declared in namespace %2">; def ext_template_spec_decl_out_of_scope : ExtWarn< + "first declaration of %select{class template|class template partial|" + "function template|member function|static data member|member class|" + "member enumeration}0 specialization of %1 outside namespace %2 is a " + "C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning< "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 must " - "originally be declared in namespace %2; accepted as a C++11 extension">, - InGroup<CXX11>; + "function|static data member|member class|member enumeration}0 " + "specialization of %1 outside namespace %2 is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_template_spec_redecl_out_of_scope : Error< "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 not in a " - "namespace enclosing %2">; + "function|static data member|member class|member enumeration}0 " + "specialization of %1 not in a namespace enclosing %2">; def err_template_spec_redecl_global_scope : Error< "%select{class template|class template partial|function template|member " - "function|static data member|member class}0 specialization of %1 must occur " - "at global scope">; + "function|static data member|member class|member enumeration}0 " + "specialization of %1 must occur at global scope">; def err_spec_member_not_instantiated : Error< "specialization of member %q0 does not specialize an instantiated member">; def note_specialized_decl : Note<"attempt to specialize declaration here">; @@ -2303,7 +2548,7 @@ def err_function_template_spec_no_match : Error< "no function template matches function template specialization %0">; def err_function_template_spec_ambiguous : Error< "function template specialization %0 ambiguously refers to more than one " - "function template; explicitly specify%select{|additional }1 template " + "function template; explicitly specify%select{| additional}1 template " "arguments to identify a particular function template">; def note_function_template_spec_matched : Note< "function template matches specialization %0">; @@ -2315,7 +2560,7 @@ def err_template_recursion_depth_exceeded : Error< "recursive template instantiation exceeded maximum depth of %0">, DefaultFatal, NoSFINAE; def note_template_recursion_depth : Note< - "use -ftemplate-depth-N to increase recursive template instantiation depth">; + "use -ftemplate-depth=N to increase recursive template instantiation depth">; def err_template_instantiate_within_definition : Error< "%select{implicit|explicit}0 instantiation of template %1 within its" @@ -2334,6 +2579,8 @@ def note_function_template_spec_here : Note< "in instantiation of function template specialization %q0 requested here">; def note_template_static_data_member_def_here : Note< "in instantiation of static data member %q0 requested here">; +def note_template_enum_def_here : Note< + "in instantiation of enumeration %q0 requested here">; def note_template_type_alias_instantiation_here : Note< "in instantiation of template type alias %0 requested here">; @@ -2376,10 +2623,12 @@ def ext_explicit_instantiation_after_specialization : Extension< "explicit instantiation of %0 that occurs after an explicit " "specialization will be ignored (C++11 extension)">, InGroup<CXX11>; +def warn_cxx98_compat_explicit_instantiation_after_specialization : Warning< + "explicit instantiation of %0 that occurs after an explicit " + "specialization is incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def note_previous_template_specialization : Note< "previous template specialization is here">; -def err_explicit_instantiation_enum : Error< - "explicit instantiation of enumeration type %0">; def err_explicit_instantiation_nontemplate_type : Error< "explicit instantiation of non-templated type %0">; def note_nontemplate_decl_here : Note< @@ -2392,10 +2641,10 @@ def err_explicit_instantiation_must_be_global : Error< "explicit instantiation of %0 must occur at global scope">; def warn_explicit_instantiation_out_of_scope_0x : Warning< "explicit instantiation of %0 not in a namespace enclosing %1">, - InGroup<CXX11Compat>; + InGroup<CXX11Compat>, DefaultIgnore; def warn_explicit_instantiation_must_be_global_0x : Warning< "explicit instantiation of %0 must occur at global scope">, - InGroup<CXX11Compat>; + InGroup<CXX11Compat>, DefaultIgnore; def err_explicit_instantiation_requires_name : Error< "explicit instantiation declaration requires a name">; @@ -2420,16 +2669,19 @@ def note_explicit_instantiation_candidate : Note< "explicit instantiation candidate function template here %0">; def err_explicit_instantiation_inline : Error< "explicit instantiation cannot be 'inline'">; +def warn_explicit_instantiation_inline_0x : Warning< + "explicit instantiation cannot be 'inline'">, InGroup<CXX11Compat>, + DefaultIgnore; def err_explicit_instantiation_constexpr : Error< "explicit instantiation cannot be 'constexpr'">; def ext_explicit_instantiation_without_qualified_id : Extension< "qualifier in explicit instantiation of %q0 requires a template-id " "(a typedef is not permitted)">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< - "explicit instantiation of %q0 must occur in %1">; + "explicit instantiation of %q0 must occur in namespace %1">; def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning< - "explicit instantiation of %q0 must occur in %1">, - InGroup<CXX11Compat>; + "explicit instantiation of %q0 must occur in namespace %1">, + InGroup<CXX11Compat>, DefaultIgnore; def err_explicit_instantiation_undefined_member : Error< "explicit instantiation of undefined %select{member class|member function|" "static data member}0 %1 of class template %2">; @@ -2454,6 +2706,9 @@ def warn_typename_missing : ExtWarn< InGroup<DiagGroup<"typename-missing">>; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup<CXX11>; +def warn_cxx98_compat_typename_outside_of_template : Warning< + "use of 'typename' outside of a template is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_typename_refers_to_using_value_decl : Error< "typename specifier refers to a dependent using declaration for a value " "%0 in %1">; @@ -2462,8 +2717,6 @@ def note_using_value_decl_missing_typename : Note< def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; -def err_template_kw_refers_to_function_template : Error< - "%0 following the 'template' keyword refers to a function template">; def err_template_kw_refers_to_class_template : Error< "'%0%1' instantiated to a class template, not a function template">; def note_referenced_class_template : Error< @@ -2472,6 +2725,9 @@ def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; def ext_template_outside_of_template : ExtWarn< "'template' keyword outside of a template">, InGroup<CXX11>; +def warn_cxx98_compat_template_outside_of_template : Warning< + "use of 'template' keyword outside of a template is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_non_type_template_in_nested_name_specifier : Error< "qualified name refers into a specialization of function template '%0'">; @@ -2480,6 +2736,8 @@ def err_template_id_not_a_type : Error< def note_template_declared_here : Note< "%select{function template|class template|type alias template|template template parameter}0 " "%1 declared here">; +def note_parameter_type : Note< + "parameter of type %0 is declared here">; // C++11 Variadic Templates def err_template_param_pack_default_arg : Error< @@ -2503,25 +2761,29 @@ def err_unexpanded_parameter_pack_0 : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" - "non-type template parameter type|exception type|partial specialization}0 " + "non-type template parameter type|exception type|partial specialization|" + "__if_exists name|__if_not_exists name}0 " "contains an unexpanded parameter pack">; def err_unexpanded_parameter_pack_1 : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" - "non-type template parameter type|exception type|partial specialization}0 " + "non-type template parameter type|exception type|partial specialization|" + "__if_exists name|__if_not_exists name}0 " "contains unexpanded parameter pack %1">; def err_unexpanded_parameter_pack_2 : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" - "non-type template parameter type|exception type|partial specialization}0 " + "non-type template parameter type|exception type|partial specialization|" + "__if_exists name|__if_not_exists name}0 " "contains unexpanded parameter packs %1 and %2">; def err_unexpanded_parameter_pack_3_or_more : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" - "non-type template parameter type|exception type|partial specialization}0 " + "non-type template parameter type|exception type|partial specialization|" + "__if_exists name|__if_not_exists name}0 " "contains unexpanded parameter packs %1, %2, ...">; def err_pack_expansion_without_parameter_packs : Error< @@ -2576,6 +2838,8 @@ def warn_unavailable_fwdclass_message : Warning< def note_unavailable_here : Note< "%select{declaration|function}0 has been explicitly marked " "%select{unavailable|deleted|deprecated}1 here">; +def note_implicitly_deleted : Note< + "explicitly defaulted function was implicitly deleted here">; def warn_not_enough_argument : Warning< "not enough variable arguments in %0 declaration to fit a sentinel">, InGroup<Sentinel>; @@ -2599,6 +2863,37 @@ def err_definition_of_explicitly_defaulted_member : Error< def err_redefinition_extern_inline : Error< "redefinition of a 'extern inline' function %0 is not supported in " "%select{C99 mode|C++}1">; +def warn_cxx98_compat_friend_redefinition : Warning< + "friend function %0 would be implicitly redefined in C++98">, + InGroup<CXX98Compat>, DefaultIgnore; + +def note_deleted_dtor_no_operator_delete : Note< + "virtual destructor requires an unambiguous, accessible 'operator delete'">; +def note_deleted_special_member_class_subobject : Note< + "%select{default constructor|copy constructor|move constructor|" + "copy assignment operator|move assignment operator|destructor}0 of " + "%select{||||union }4%1 is implicitly deleted because " + "%select{base class %3|field %3}2 has " + "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 " + "%select{%select{default constructor|copy constructor|move constructor|copy " + "assignment operator|move assignment operator|destructor}0|destructor}5" + "%select{||s||}4">; +def note_deleted_default_ctor_uninit_field : Note< + "default constructor of %0 is implicitly deleted because field %1 of " + "%select{reference|const-qualified}3 type %2 would not be initialized">; +def note_deleted_default_ctor_all_const : Note< + "default constructor of %0 is implicitly deleted because all " + "%select{data members|data members of an anonymous union member}1" + " are const-qualified">; +def note_deleted_copy_ctor_rvalue_reference : Note< + "copy constructor of %0 is implicitly deleted because field %1 is of " + "rvalue reference type %2">; +def note_deleted_copy_user_declared_move : Note< + "copy %select{constructor|assignment operator}0 is implicitly deleted because" + " %1 has a user-declared move %select{constructor|assignment operator}2">; +def note_deleted_assign_field : Note< + "%select{copy|move}0 assignment operator of %0 is implicitly deleted " + "because field %1 is of %select{reference|const-qualified}3 type %2">; // This should eventually be an error. def warn_undefined_internal : Warning< @@ -2606,9 +2901,11 @@ def warn_undefined_internal : Warning< DiagGroup<"undefined-internal">; def note_used_here : Note<"used here">; -def warn_redefinition_of_typedef : Warning< - "redefinition of typedef %0 is invalid in C">, - InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; +def warn_redefinition_of_typedef : ExtWarn< + "redefinition of typedef %0 is a C11 feature">, + InGroup<DiagGroup<"typedef-redefinition"> >; +def err_redefinition_variably_modified_typedef : Error< + "redefinition of %select{typedef|type alias}0 for variably-modified type %1">; def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; @@ -2632,6 +2929,9 @@ def err_redefinition_different_type : Error< "redefinition of %0 with a different type">; def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; +def warn_forward_class_redefinition : Warning< + "redefinition of forward class %0 of a typedef name of an object type is ignored">, + InGroup<DiagGroup<"objc-forward-class-redefinition">>; def err_redefinition_different_typedef : Error< "%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">; def err_tag_reference_non_tag : Error< @@ -2692,6 +2992,9 @@ def err_vm_func_decl : Error< "function declaration cannot have variably modified type">; def err_array_too_large : Error< "array is too large (%0 elements)">; +def warn_array_new_too_large : Warning<"array is too large (%0 elements)">, + // FIXME PR11644: ", will throw std::bad_array_new_length at runtime" + InGroup<DiagGroup<"bad-array-new-length">>; // -Wpadded, -Wpacked def warn_padded_struct_field : Warning< @@ -2707,6 +3010,9 @@ def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore; def err_typecheck_negative_array_size : Error<"array size is negative">; +def warn_typecheck_negative_array_new_size : Warning<"array size is negative">, + // FIXME PR11644: ", will throw std::bad_array_new_length at runtime" + InGroup<DiagGroup<"bad-array-new-length">>; def warn_typecheck_function_qualifiers : Warning< "qualifier on function type %0 has unspecified behavior">; def err_typecheck_invalid_restrict_not_pointer : Error< @@ -2719,8 +3025,9 @@ def ext_typecheck_zero_array_size : Extension< "zero size arrays are an extension">; def err_typecheck_zero_array_size : Error< "zero-length arrays are not permitted in C++">; -def err_at_least_one_initializer_needed_to_size_array : Error< - "at least one initializer value required to size array">; +def warn_typecheck_zero_static_array_size : Warning< + "'static' has no effect on zero-length arrays">, + InGroup<DiagGroup<"array-bounds">>; def err_array_size_non_int : Error<"size of array has non-integer type %0">; def err_init_element_not_constant : Error< "initializer element is not a compile-time constant">; @@ -2731,8 +3038,6 @@ def err_block_extern_cant_init : Error< def warn_extern_init : Warning<"'extern' variable has an initializer">; def err_variable_object_no_init : Error< "variable-sized object may not be initialized">; -def err_array_init_list_required : Error< - "initialization with '{...}' expected for array">; def err_excess_initializers : Error< "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; def warn_excess_initializers : ExtWarn< @@ -2756,14 +3061,31 @@ def ext_complex_component_init : Extension< "complex initialization specifying real and imaginary components " "is an extension">, InGroup<DiagGroup<"complex-component-init">>; def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; +def warn_cxx98_compat_empty_scalar_initializer : Warning< + "scalar initialized from empty initializer list is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; -def err_init_list_variable_narrowing : Error< +def err_init_list_type_narrowing_sfinae : Error< + "type %0 cannot be narrowed to %1 in initializer list">; +def err_init_list_type_narrowing : ExtWarn< + "type %0 cannot be narrowed to %1 in initializer list">, + InGroup<CXX11Narrowing>, DefaultError; +def err_init_list_variable_narrowing_sfinae : Error< "non-constant-expression cannot be narrowed from type %0 to %1 in " "initializer list">; -def err_init_list_constant_narrowing : Error< +def err_init_list_variable_narrowing : ExtWarn< + "non-constant-expression cannot be narrowed from type %0 to %1 in " + "initializer list">, InGroup<CXX11Narrowing>, DefaultError; +def err_init_list_constant_narrowing_sfinae : Error< "constant expression evaluates to %0 which cannot be narrowed to type %1">; +def err_init_list_constant_narrowing : ExtWarn< + "constant expression evaluates to %0 which cannot be narrowed to type %1">, + InGroup<CXX11Narrowing>, DefaultError; +def warn_init_list_type_narrowing : Warning< + "type %0 cannot be narrowed to %1 in initializer list in C++11">, + InGroup<CXX11Narrowing>, DefaultIgnore; def warn_init_list_variable_narrowing : Warning< "non-constant-expression cannot be narrowed from type %0 to %1 in " "initializer list in C++11">, @@ -2789,7 +3111,7 @@ def err_anon_bitfield_width_exceeds_type_size : Error< "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">; def err_incorrect_number_of_vector_initializers : Error< "number of elements must be either one or match the size of the vector">; - + // Used by C++ which allows bit-fields that are wider than the type. def warn_bitfield_width_exceeds_type_size: Warning< "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be " @@ -2801,6 +3123,9 @@ def warn_anon_bitfield_width_exceeds_type_size : Warning< def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, InGroup<DiagGroup<"missing-braces">>, DefaultIgnore; +def err_missing_braces : Error< + "cannot omit braces around initialization of subobject when using direct " + "list-initialization">; def err_redefinition_of_label : Error<"redefinition of label %0">; def err_undeclared_label_use : Error<"use of undeclared label %0">; @@ -2810,17 +3135,28 @@ def warn_unused_label : Warning<"unused label %0">, def err_goto_into_protected_scope : Error<"goto into protected scope">; def warn_goto_into_protected_scope : ExtWarn<"goto into protected scope">, InGroup<Microsoft>; +def warn_cxx98_compat_goto_into_protected_scope : Warning< + "goto would jump into protected scope in C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_switch_into_protected_scope : Error< "switch case is in protected scope">; +def warn_cxx98_compat_switch_into_protected_scope : Warning< + "switch case would be in a protected scope in C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def err_indirect_goto_in_protected_scope : Error< "indirect goto might cross protected scopes">; +def warn_cxx98_compat_indirect_goto_in_protected_scope : Warning< + "indirect goto might cross protected scopes in C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def note_indirect_goto_target : Note<"possible target of indirect goto">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; def note_protected_by_variable_nontriv_destructor : Note< "jump bypasses variable with a non-trivial destructor">; +def note_protected_by_variable_non_pod : Note< + "jump bypasses initialization of non-POD variable">; def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< @@ -2896,9 +3232,11 @@ def err_flexible_array_empty_struct : Error< def err_flexible_array_has_nonpod_type : Error< "flexible array member %0 of non-POD element type %1">; def ext_flexible_array_in_struct : Extension< - "%0 may not be nested in a struct due to flexible array member">; + "%0 may not be nested in a struct due to flexible array member">, + InGroup<FlexibleArrayExtensions>; def ext_flexible_array_in_array : Extension< - "%0 may not be used as an array element due to flexible array member">; + "%0 may not be used as an array element due to flexible array member">, + InGroup<FlexibleArrayExtensions>; def err_flexible_array_init : Error< "initialization of flexible array member is not allowed">; def ext_flexible_array_empty_aggregate_ms : Extension< @@ -2913,18 +3251,29 @@ def ext_flexible_array_empty_aggregate_gnu : Extension< def ext_flexible_array_union_gnu : Extension< "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>; -let CategoryName = "Automatic Reference Counting Issue" in { +let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. + +let CategoryName = "ARC Weak References" in { + def err_arc_weak_no_runtime : Error< "the current deployment target does not support automated __weak references">; def err_arc_unsupported_weak_class : Error< "class is incompatible with __weak references">; def err_arc_weak_unavailable_assign : Error< "assignment of a weak-unavailable object to a __weak object">; +def err_arc_weak_unavailable_property : Error< + "synthesis of a weak-unavailable property is disallowed " + "because it requires synthesis of an ivar of the __weak object">; def err_arc_convesion_of_weak_unavailable : Error< "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to" " a __weak object of type %2">; + +} // end "ARC Weak References" category + +let CategoryName = "ARC Restrictions" in { + def err_arc_illegal_explicit_message : Error< "ARC forbids explicit message send of %0">; def err_arc_unused_init_message : Error< @@ -2935,8 +3284,10 @@ def err_arc_mismatched_cast : Error< "%select{%2|a non-Objective-C pointer type %2|a block pointer|" "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1" " to %3 is disallowed with ARC">; +def err_arc_nolifetime_behavior : Error< + "explicit ownership qualifier on cast result has no effect">; def err_arc_objc_object_in_struct : Error< - "ARC forbids Objective-C objects in structs or unions">; + "ARC forbids %select{Objective-C objects|blocks}0 in structs or unions">; def err_arc_objc_property_default_assign_on_object : Error< "ARC forbids synthesizing a property of an Objective-C object " "with unspecified ownership or storage attribute">; @@ -2944,6 +3295,9 @@ def err_arc_illegal_selector : Error< "ARC forbids use of %0 in a @selector">; def err_arc_illegal_method_def : Error< "ARC forbids implementation of %0">; + +} // end "ARC Restrictions" category + def err_arc_lost_method_convention : Error< "method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 " "method, but its implementation doesn't match because %select{" @@ -2956,8 +3310,10 @@ def note_arc_gained_method_convention : Note< "declaration in interface is not in the '%select{alloc|copy|init|new}0' " "family because %select{its result type is not an object pointer|" "its result type is unrelated to its receiver type}1">; -def err_typecheck_arr_assign_self : Error< +def err_typecheck_arc_assign_self : Error< "cannot assign to 'self' outside of a method in the init family">; +def err_typecheck_arc_assign_self_class_method : Error< + "cannot assign to 'self' in a class method">; def err_typecheck_arr_assign_enumeration : Error< "fast enumeration variables can't be modified in ARC by default; " "declare the variable __strong to allow this">; @@ -2988,6 +3344,9 @@ def warn_err_new_delete_object_array : Warning< def err_arc_autoreleasing_var : Error< "%select{__block variables|global variables|fields|ivars}0 cannot have " "__autoreleasing ownership">; +def err_arc_autoreleasing_capture : Error< + "cannot capture __autoreleasing variable in a " + "%select{block|lambda by copy}0">; def err_arc_thread_ownership : Error< "thread-local variable has non-trivial ownership: type is %0">; def err_arc_indirect_no_ownership : Error< @@ -3011,17 +3370,26 @@ def err_arc_may_not_respond : Error< "no visible @interface for %0 declares the selector %1">; def err_arc_receiver_forward_instance : Error< "receiver type %0 for instance message is a forward declaration">; +def warn_receiver_forward_instance : Warning< + "receiver type %0 for instance message is a forward declaration">, + InGroup<DiagGroup<"receiver-forward-class">>, DefaultIgnore; def err_arc_collection_forward : Error< "collection expression type %0 is a forward declaration">; def err_arc_multiple_method_decl : Error< "multiple methods named %0 found with mismatched result, " "parameter type or attributes">; + +let CategoryName = "ARC Retain Cycle" in { + def warn_arc_retain_cycle : Warning< "capturing %0 strongly in this block is likely to lead to a retain cycle">, InGroup<ARCRetainCycles>; def note_arc_retain_cycle_owner : Note< "block will be retained by %select{the captured object|an object strongly " "retained by the captured object}0">; + +} // end "ARC Retain Cycle" category + def note_nontrivial_objc_ownership : Note< "because type %0 has %select{no|no|__strong|__weak|__autoreleasing}1 " "ownership">; @@ -3029,6 +3397,8 @@ def warn_arc_object_memaccess : Warning< "%select{destination for|source of}0 this %1 call is a pointer to " "ownership-qualified type %2">, InGroup<ARCNonPodMemAccess>; +let CategoryName = "ARC and @properties" in { + def err_arc_strong_property_ownership : Error< "existing ivar %1 for strong property %0 may not be " "%select{|__unsafe_unretained||__weak}2">; @@ -3038,10 +3408,15 @@ def err_arc_assign_property_ownership : Error< def err_arc_inconsistent_property_ownership : Error< "%select{|unsafe_unretained|strong|weak}1 property %0 may not also be " "declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">; + +} // end "ARC and @properties" category + def err_arc_atomic_ownership : Error< "cannot perform atomic operation on a pointer to type %0: type has " "non-trivial ownership">; +let CategoryName = "ARC Casting Rules" in { + def err_arc_bridge_cast_incompatible : Error< "incompatible types casting %0 to %1 with a %select{__bridge|" "__bridge_transfer|__bridge_retained}2 cast">; @@ -3050,14 +3425,19 @@ def err_arc_bridge_cast_wrong_kind : Error< "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|" "__bridge_transfer|__bridge_retained}4">; def err_arc_cast_requires_bridge : Error< - "cast of %select{Objective-C|block|C}0 pointer type %1 to " - "%select{Objective-C|block|C}2 pointer type %3 requires a bridged cast">; + "%select{cast|implicit conversion}0 of %select{Objective-C|block|C}1 " + "pointer type %2 to %select{Objective-C|block|C}3 pointer type %4 " + "requires a bridged cast">; def note_arc_bridge : Note< "use __bridge to convert directly (no change in ownership)">; def note_arc_bridge_transfer : Note< - "use __bridge_transfer to transfer ownership of a +1 %0 into ARC">; + "use %select{__bridge_transfer|CFBridgingRelease call}1 to transfer " + "ownership of a +1 %0 into ARC">; def note_arc_bridge_retained : Note< - "use __bridge_retained to make an ARC object available as a +1 %0">; + "use %select{__bridge_retained|CFBridgingRetain call}1 to make an " + "ARC object available as a +1 %0">; + +} // ARC Casting category } // ARC category name @@ -3086,15 +3466,11 @@ def err_illegal_decl_mempointer_in_nonclass : Error< def err_mempointer_in_nonclass_type : Error< "member pointer refers into non-class type %0">; def err_reference_to_void : Error<"cannot form a reference to 'void'">; -def err_qualified_block_pointer_type : Error< - "qualifier specification on block pointer type not allowed">; def err_nonfunction_block_type : Error< "block pointer to non-function type is invalid">; def err_return_block_has_expr : Error<"void block should not return a value">; def err_block_return_missing_expr : Error< "non-void block should return a value">; -def err_block_with_return_type_requires_args : Error< - "block with explicit return type requires argument list">; def err_func_def_incomplete_result : Error< "incomplete result type %0 in function definition">; def err_atomic_specifier_bad_type : Error< @@ -3105,9 +3481,6 @@ def err_atomic_specifier_bad_type : Error< // Expressions. def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>; -def err_sizeof_alignof_overloaded_function_type : Error< - "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " - "overloaded function">; def ext_sizeof_void_type : Extension< "invalid application of '%select{sizeof|__alignof|vec_step}0' to a void " "type">, InGroup<PointerArith>; @@ -3124,7 +3497,8 @@ def err_offsetof_record_type : Error< "offsetof requires struct, union, or class type, %0 invalid">; def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; def ext_offsetof_extended_field_designator : Extension< - "using extended field designator is an extension">; + "using extended field designator is an extension">, + InGroup<DiagGroup<"extended-offsetof">>; def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup<InvalidOffsetof>; def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">; @@ -3185,6 +3559,12 @@ def warn_self_assignment : Warning< "explicitly assigning a variable of type %0 to itself">, InGroup<SelfAssignment>, DefaultIgnore; +def warn_string_plus_int : Warning< + "adding %0 to a string does not append to the string">, + InGroup<StringPlusInt>; +def note_string_plus_int_silence : Note< + "use array indexing to silence this warning">; + def warn_sizeof_array_param : Warning< "sizeof on array function parameter will return size of %0 instead of %1">, InGroup<SizeofArrayArgument>; @@ -3232,7 +3612,7 @@ def err_typecheck_member_reference_unknown : Error< "cannot refer to member %0 in %1 with '%select{.|->}2'">; def err_member_reference_needs_call : Error< "base of member reference is a function; perhaps you meant to call " - "it%select{| with no arguments}?">; + "it%select{| with no arguments}0?">; def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, InGroup<CharSubscript>, DefaultIgnore; @@ -3244,6 +3624,11 @@ def err_member_not_yet_instantiated : Error< def note_non_instantiated_member_here : Note< "not-yet-instantiated member is declared here">; +def err_enumerator_does_not_exist : Error< + "enumerator %0 does not exist in instantiation of %1">; +def note_enum_specialized_here : Note< + "enum %0 was explicitly specialized here">; + def err_member_redeclared : Error<"class member cannot be redeclared">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< @@ -3252,13 +3637,11 @@ def err_member_def_does_not_match : Error< "out-of-line definition of %0 does not match any declaration in %1">; def err_member_def_does_not_match_suggest : Error< "out-of-line definition of %0 does not match any declaration in %1; " - "did you mean %2">; + "did you mean %2?">; def err_member_def_does_not_match_ret_type : Error< "out-of-line definition of %q0 differs from the declaration in the return type">; def err_nonstatic_member_out_of_line : Error< "non-static data member defined out-of-line">; -def err_nonstatic_flexible_variable : Error< - "non-static initialization of a variable with flexible array member">; def err_qualified_typedef_declarator : Error< "typedef declarator cannot be qualified">; def err_qualified_param_declarator : Error< @@ -3313,7 +3696,11 @@ def err_array_init_non_constant_array : Error< "cannot initialize array of type %0 with non-constant array of type %1">; def ext_array_init_copy : Extension< "initialization of an array of type %0 from a compound literal of type %1 is " - "a GNU extension">; + "a GNU extension">, InGroup<GNU>; +// This is intentionally not disabled by -Wno-gnu. +def ext_array_init_parens : ExtWarn< + "parenthesized initialization of a member array is a GNU extension">, + InGroup<DiagGroup<"gnu-array-member-paren-init">>, DefaultError; def warn_deprecated_string_literal_conversion : Warning< "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; @@ -3355,14 +3742,10 @@ def warn_pointer_indirection_from_incompatible_type : Warning< "behavior.">, InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore; -def err_assignment_requires_nonfragile_object : Error< - "cannot assign to class object in non-fragile ABI (%0 invalid)">; -def err_direct_interface_unsupported : Error< - "indirection to an interface is not supported (%0 invalid)">; +def err_objc_object_assignment : Error< + "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; -def err_typecheck_sub_ptr_object : Error< - "subtraction of pointer %0 requires pointee to be a complete object type">; def err_typecheck_sub_ptr_compatible : Error< "%0 and %1 are not pointers to compatible types">; def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn< @@ -3383,13 +3766,13 @@ def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< "comparison of distinct pointer types (%0 and %1)">; def ext_typecheck_cond_incompatible_operands : ExtWarn< "incompatible operand types (%0 and %1)">; +def err_cond_voidptr_arc : Error < + "operands to conditional of types %0 and %1 are incompatible in ARC mode">; 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">; def err_stmtexpr_file_scope : Error< "statement expression not allowed at file scope">; @@ -3414,26 +3797,15 @@ def warn_null_in_comparison_operation : Warning< InGroup<DiagGroup<"null-arithmetic">>; def err_invalid_this_use : Error< - "invalid use of 'this' outside of a nonstatic member function">; + "invalid use of 'this' outside of a non-static member function">; def err_invalid_member_use_in_static_method : Error< "invalid use of member %0 in static member function">; def err_invalid_qualified_function_type : Error< - "type qualifier is not allowed on this function">; -def err_invalid_ref_qualifier_function_type : Error< - "ref-qualifier '%select{&&|&}0' is only allowed on non-static member functions," - " member function pointers, and typedefs of function types">; -def ext_qualified_function_type_template_arg : ExtWarn< - "template argument of '%0' qualified function type is a GNU extension">, - InGroup<GNU>; - -def err_invalid_qualified_function_pointer : Error< - "type qualifier is not allowed on this function %select{pointer|reference}0">; -def err_invalid_qualified_typedef_function_type_use : Error< - "a qualified function type cannot be used to declare a " - "%select{static member|nonmember}0 function">; -def err_invalid_ref_qualifier_typedef_function_type_use : Error< - "%select{static member|nonmember}0 function cannot have a ref-qualifier " - "'%select{&&|&}1'">; + "%select{static |non-}0member function %select{of type %2 |}1" + "cannot have '%3' qualifier">; +def err_compound_qualified_function_type : Error< + "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1" + "cannot have '%3' qualifier">; def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " @@ -3441,13 +3813,17 @@ def err_ref_qualifier_overload : Error< "without a ref-qualifier|with ref-qualifier '&'|with ref-qualifier '&&'}1">; def err_invalid_non_static_member_use : Error< - "invalid use of nonstatic data member %0">; + "invalid use of non-static data member %0">; +def err_nested_non_static_member_use : Error< + "%select{call to non-static member function|use of non-static data member}0 " + "%2 of %1 from nested type %3">; +def warn_cxx98_compat_non_static_member_use : Warning< + "use of non-static data member %0 in an unevaluated context is " + "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_invalid_incomplete_type_use : Error< "invalid use of incomplete type %0">; def err_builtin_func_cast_more_than_one_arg : Error< "function-style cast to a builtin type can only take one argument">; -def err_builtin_direct_init_more_than_one_arg : Error< - "initializer of a builtin type can only take one argument">; def err_value_init_for_array_type : Error< "array types cannot be value-initialized">; def warn_format_nonliteral_noargs : Warning< @@ -3470,13 +3846,43 @@ def err_invalid_property_name : Error< "%0 is not a valid property name (accessing an object of type %1)">; def err_getter_not_found : Error< "expected getter method not found on object of type %0">; +def err_objc_subscript_method_not_found : Error< + "expected method to %select{read|write}1 %select{dictionary|array}2 element not " + "found on object of type %0">; +def err_objc_subscript_index_type : Error< + "method index parameter type %0 is not integral type">; +def err_objc_subscript_key_type : Error< + "method key parameter type %0 is not object type">; +def err_objc_subscript_dic_object_type : Error< + "method object parameter type %0 is not object type">; +def err_objc_subscript_object_type : Error< + "cannot assign to this %select{dictionary|array}1 because assigning method's 2nd parameter" + " of type %0 is not an objective-C pointer type">; +def err_objc_subscript_base_type : Error< + "%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">; +def err_objc_multiple_subscript_type_conversion : Error< + "indexing expression is invalid because subscript type %0 has " + "multiple type conversion functions">; +def err_objc_subscript_type_conversion : Error< + "indexing expression is invalid because subscript type %0 is not an integral" + " or objective-C pointer type">; +def err_objc_subscript_pointer : Error< + "indexing expression is invalid because subscript type %0 is not an" + " objective-C pointer">; +def err_objc_indexing_method_result_type : Error< + "method for accessing %select{dictionary|array}1 element must have Objective-C" + " object return type instead of %0">; +def err_objc_index_incomplete_class_type : Error< + "objective-C index expression has incomplete class type %0">; +def err_illegal_container_subscripting_op : Error< + "illegal operation on objective-c container subscripting">; def err_property_not_found_forward_class : Error< "property %0 cannot be found in forward class object %1">; def err_property_not_as_forward_class : Error< "property %0 refers to an incomplete Objective-C class %1 " "(with no @interface available)">; def note_forward_class : Note< - "forward class is declared here">; + "forward declaration of class here">; def err_duplicate_property : Error< "property has a previous declaration">; def ext_gnu_void_ptr : Extension< @@ -3486,16 +3892,22 @@ def ext_gnu_ptr_func_arith : Extension< "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function " "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">, InGroup<PointerArith>; -def error_readonly_property_assignment : Error< - "assigning to property with 'readonly' attribute not allowed">; def error_readonly_message_assignment : Error< "assigning to 'readonly' return result of an objective-c message not allowed">; def ext_integer_increment_complex : Extension< "ISO C does not support '++'/'--' on complex integer type %0">; def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; -def error_nosetter_property_assignment : Error< - "setter method is needed to assign to object using property" " assignment syntax">; +def err_nosetter_property_assignment : Error< + "%select{assignment to readonly property|" + "no setter method %1 for assignment to property}0">; +def err_nosetter_property_incdec : Error< + "%select{%select{increment|decrement}1 of readonly property|" + "no setter method %2 for %select{increment|decrement}1 of property}0">; +def err_nogetter_property_compound_assignment : Error< + "a getter method is needed to perform a compound assignment on a property">; +def err_nogetter_property_incdec : Error< + "no getter method %1 for %select{increment|decrement} of property">; def error_no_subobject_property_setting : Error< "expression is not assignable">; def err_qualified_objc_access : Error< @@ -3553,8 +3965,6 @@ def warn_register_objc_catch_parm : Warning< "'register' storage specifier on @catch parameter will be ignored">; def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; -def err_objc_pointer_cxx_catch_gnu : Error< - "can't catch Objective C exceptions in C++ in the GNU runtime">; def warn_objc_pointer_cxx_catch_fragile : Warning< "can not catch an exception thrown with @throw in C++ in the non-unified " "exception model">, InGroup<ObjCNonUnifiedException>; @@ -3566,12 +3976,12 @@ def err_incomplete_type_objc_at_encode : Error< def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " "use @synthesize, @dynamic or provide a method implementation " - "in this class implementation">; + "in this class implementation">, + InGroup<ObjCPropertyImpl>; def warn_setter_getter_impl_required_in_category : Warning< "property %0 requires method %1 to be defined - " - "use @dynamic or provide a method implementation in this category">; -def note_property_impl_required : Note< - "implementation is here">; + "use @dynamic or provide a method implementation in this category">, + InGroup<ObjCPropertyImpl>; def note_parameter_named_here : Note< "passing argument to parameter %0 here">; def note_parameter_here : Note< @@ -3604,6 +4014,9 @@ def err_bad_const_cast_dest : Error< "which is not a reference, pointer-to-object, or pointer-to-data-member">; def ext_cast_fn_obj : Extension< "cast between pointer-to-function and pointer-to-object is an extension">; +def warn_cxx98_compat_cast_fn_obj : Warning< + "cast between pointer-to-function and pointer-to-object is incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_bad_reinterpret_cast_small_int : Error< "cast from pointer to smaller type %2 loses information">; def err_bad_cxx_cast_vector_to_scalar_different_size : Error< @@ -3625,7 +4038,6 @@ def err_bad_static_cast_member_pointer_nonmp : Error< def err_bad_cxx_cast_member_pointer_size : Error< "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " "type %1 to member pointer type %2 of different size">; -def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; def err_bad_reinterpret_cast_reference : Error< "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; def warn_undefined_reinterpret_cast : Warning< @@ -3675,7 +4087,8 @@ 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">; + "array size expression must have integral or %select{|unscoped }0" + "enumeration type, not %1">; def err_array_size_incomplete_type : Error< "array size expression has incomplete class type %0">; def err_array_size_explicit_conversion : Error< @@ -3689,6 +4102,10 @@ def ext_array_size_conversion : Extension< "implicit conversion from array size expression of type %0 to " "%select{integral|enumeration}1 type %2 is a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_array_size_conversion : Warning< + "implicit conversion from array size expression of type %0 to " + "%select{integral|enumeration}1 type %2 is incompatible with C++98">, + InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_address_space_qualified_new : Error< "'new' cannot allocate objects of type %0 in address space '%1'">; def err_address_space_qualified_delete : Error< @@ -3703,7 +4120,8 @@ def ext_delete_void_ptr_operand : ExtWarn< def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< - "deleting pointer to incomplete type %0 may cause undefined behaviour">; + "deleting pointer to incomplete type %0 may cause undefined behaviour">, + InGroup<DiagGroup<"delete-incomplete">>; def err_delete_incomplete_class_type : Error< "deleting incomplete class type %0; no conversions to pointer type">; def warn_delete_array_type : Warning< @@ -3717,10 +4135,10 @@ def note_member_declared_here : Note< def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< "incrementing expression of type bool is deprecated">, InGroup<Deprecated>; -def ext_catch_incomplete_ptr : ExtWarn< - "ISO C++ forbids catching a pointer to incomplete type %0">; -def ext_catch_incomplete_ref : ExtWarn< - "ISO C++ forbids catching a reference to incomplete type %0">; +def err_catch_incomplete_ptr : Error< + "cannot catch pointer to incomplete type %0">; +def err_catch_incomplete_ref : Error< + "cannot catch reference to incomplete type %0">; def err_catch_incomplete : Error<"cannot catch incomplete type %0">; def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">; def err_qualified_catch_declarator : Error< @@ -3728,8 +4146,6 @@ def err_qualified_catch_declarator : Error< def err_early_catch_all : Error<"catch-all handler must come last">; def err_bad_memptr_rhs : Error< "right hand operand to %0 has non pointer-to-member type %1">; -def err_memptr_rhs_to_incomplete : Error< - "cannot dereference pointer into incomplete class type %0">; def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; @@ -3757,6 +4173,10 @@ def note_hidden_overloaded_virtual_declared_here : Note< def warn_using_directive_in_header : Warning< "using namespace directive in global context in header">, InGroup<HeaderHygiene>, DefaultIgnore; +def warn_overaligned_type : Warning< + "type %0 requires %1 bytes of alignment and the default allocator only " + "guarantees %2 bytes">, + InGroup<OveralignedType>, DefaultIgnore; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " @@ -3775,11 +4195,79 @@ def err_throw_incomplete_ptr : Error< def err_return_in_constructor_handler : Error< "return in the catch of a function try block of a constructor is illegal">; +let CategoryName = "Lambda Issue" in { + def err_capture_more_than_once : Error< + "%0 can appear only once in a capture list">; + def err_reference_capture_with_reference_default : Error< + "'&' cannot precede a capture when the capture default is '&'">; + def err_this_capture_with_copy_default : Error< + "'this' cannot be explicitly captured when the capture default is '='">; + def err_copy_capture_with_copy_default : Error< + "'&' must precede a capture when the capture default is '='">; + def err_capture_does_not_name_variable : Error< + "%0 in capture list does not name a variable">; + def err_capture_non_automatic_variable : Error< + "%0 cannot be captured because it does not have automatic storage " + "duration">; + def err_this_capture : Error< + "'this' cannot be %select{implicitly |}0captured in this context">; + def err_lambda_capture_block : Error< + "__block variable %0 cannot be captured in a lambda expression">; + def err_lambda_capture_anonymous_var : Error< + "unnamed variable cannot be implicitly captured in a lambda expression">; + def err_lambda_capture_vm_type : Error< + "variable %0 with variably modified type cannot be captured in " + "a lambda expression">; + def err_lambda_impcap : Error< + "variable %0 cannot be implicitly captured in a lambda with no " + "capture-default specified">; + def note_lambda_decl : Note<"lambda expression begins here">; + def err_lambda_unevaluated_operand : Error< + "lambda expression in an unevaluated operand">; + def ext_lambda_implies_void_return : ExtWarn< + "C++11 requires lambda with omitted result type to consist of a single " + "return statement">, + InGroup<LambdaExtensions>; + def err_lambda_return_init_list : Error< + "cannot deduce lambda return type from initializer list">; + def err_lambda_capture_default_arg : Error< + "lambda expression in default argument cannot capture any entity">; + def err_lambda_unexpanded_pack : Error< + "unexpanded function parameter pack capture is unsupported">; + def err_lambda_incomplete_result : Error< + "incomplete result type %0 in lambda expression">; + def err_lambda_objc_object_result : Error< + "non-pointer Objective-C class type %0 in lambda expression result">; + def ext_lambda_default_arguments : ExtWarn< + "C++11 forbids default arguments for lambda expressions">, + InGroup<LambdaExtensions>; + def err_noreturn_lambda_has_return_expr : Error< + "lambda declared 'noreturn' should not return">; + def warn_maybe_falloff_nonvoid_lambda : Warning< + "control may reach end of non-void lambda">, + InGroup<ReturnType>; + def warn_falloff_nonvoid_lambda : Warning< + "control reaches end of non-void lambda">, + InGroup<ReturnType>; + def err_access_lambda_capture : Error< + // The ERRORs represent other special members that aren't constructors, in + // hopes that someone will bother noticing and reporting if they appear + "capture of variable '%0' as type %1 calls %select{private|protected}3 " + "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}2constructor">, + AccessControl; + def note_lambda_to_block_conv : Note< + "implicit capture of lambda object due to conversion to block pointer " + "here">; +} + def err_operator_arrow_circular : Error< "circular pointer delegation detected">; def err_pseudo_dtor_base_not_scalar : Error< "object expression of non-scalar type %0 cannot be used in a " "pseudo-destructor expression">; +def ext_pseudo_dtor_on_void : ExtWarn< + "pseudo-destructors on type void are a Microsoft extension">, + InGroup<Microsoft>; def err_pseudo_dtor_type_mismatch : Error< "the type of object expression (%0) does not match the type being destroyed " "(%1) in pseudo-destructor expression">; @@ -3791,9 +4279,6 @@ def err_dtor_expr_without_call : Error< 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">; @@ -3809,10 +4294,10 @@ def err_typecheck_deleted_function : Error< "conversion function from %0 to %1 invokes a deleted function">; def err_expected_class_or_namespace : Error<"expected a class or namespace">; -def err_missing_qualified_for_redecl : Error< - "must qualify the name %0 to declare %q1 in this scope">; -def err_invalid_declarator_scope : Error< - "definition or redeclaration of %0 not in a namespace enclosing %1">; +def err_expected_class : Error<"%0 is not a class%select{ or namespace|, " + "namespace, or scoped enumeration}1">; +def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here " + "because namespace %1 does not enclose namespace %2">; def err_invalid_declarator_global_scope : Error< "definition or redeclaration of %0 cannot name the global scope">; def err_invalid_declarator_in_function : Error< @@ -3824,8 +4309,6 @@ def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; def err_incomplete_object_call : Error< "incomplete type in call to object of type %0">; -def err_incomplete_pointer_to_member_return : Error< - "incomplete return type %0 of pointer-to-member constant">; def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, @@ -3848,12 +4331,6 @@ def note_equality_comparison_to_assign : Note< def note_equality_comparison_silence : Note< "remove extraneous parentheses around the comparison to silence this warning">; -def warn_synthesized_ivar_access : Warning< - "direct access of synthesized ivar by using property access %0">, - InGroup<NonfragileAbi2>, DefaultIgnore; - -def note_global_declared_at : Note<"global variable declared here">; - // assignment related diagnostics (also for argument passing, returning, etc). // In most of these diagnostics the %2 is a value from the // Sema::AssignmentAction enumeration @@ -3863,11 +4340,24 @@ def err_typecheck_convert_incompatible : Error< "%select{from incompatible type|to parameter of incompatible type|" "from a function with incompatible result type|to incompatible type|" "with an expression of incompatible type|to parameter of incompatible type|" - "to incompatible type}2 %1; " - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">; + "to incompatible type}2 %1" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3" + "%select{|: different classes (%5 vs %6)" + "|: different number of parameters (%5 vs %6)" + "|: type mismatch at %ordinal5 parameter (%6 vs %7)" + "|: different return type (%5 vs %6)" + "|: different qualifiers (" + "%select{none|const|restrict|const and restrict|volatile|const and volatile|" + "volatile and restrict|const, volatile, and restrict}5 vs " + "%select{none|const|restrict|const and restrict|volatile|const and volatile|" + "volatile and restrict|const, volatile, and restrict}6)}4">; +def err_typecheck_missing_return_type_incompatible : Error< + "return type %0 must match previous return type %1 when %select{block " + "literal|lambda expression}2 has unspecified explicit return type">; + def warn_incompatible_qualified_id : Warning< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " @@ -3880,21 +4370,23 @@ def ext_typecheck_convert_pointer_int : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1; " - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">; + "with an expression of type|to parameter of type|to type}2 %1" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, + InGroup<IntConversion>; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1; " - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">; + "with an expression of type|to parameter of type|to type}2 %1" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, + InGroup<IntConversion>; def ext_typecheck_convert_pointer_void_func : Extension< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " @@ -3914,10 +4406,10 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn< " %0 " "%select{from|to parameter of type|from a function with result type|to type|" "with an expression of type|to parameter of type|to type}2 %1" - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">, + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, InGroup<IncompatiblePointerTypes>; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" @@ -3939,7 +4431,7 @@ def warn_incompatible_vectors : Warning< " %0 " "%select{from|to parameter of type|from a function with result type|to type|" "with an expression of type|to parameter of type|to type}2 %1">, - InGroup<VectorConversions>, DefaultIgnore; + InGroup<VectorConversion>, DefaultIgnore; def err_int_to_block_pointer : Error< "invalid block pointer conversion " "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" @@ -3970,8 +4462,6 @@ def err_typecheck_incompatible_ownership : Error< "|sending %0 to parameter of type %1" "|casting %0 to type %1}2" " changes retain/release properties of pointer">; -def err_typecheck_convert_ambiguous : Error< - "ambiguity in initializing value of type %0 with initializer of type %1">; def err_typecheck_comparison_of_distinct_blocks : Error< "comparison of distinct block types (%0 and %1)">; @@ -3990,6 +4480,8 @@ def err_typecheck_duplicate_vector_components_not_mlvalue : Error< "vector is not assignable (contains duplicate components)">; def err_block_decl_ref_not_modifiable_lvalue : Error< "variable is not assignable (missing __block type specifier)">; +def err_lambda_decl_ref_not_modifiable_lvalue : Error< + "cannot assign to a variable captured by copy in a non-mutable lambda">; def err_typecheck_call_not_function : Error< "called object type %0 is not a function or function pointer">; def err_call_incomplete_return : Error< @@ -4018,6 +4510,8 @@ def err_typecheck_call_too_many_args_at_most : Error< "expected at most %1, have %2">; def note_callee_decl : Note< "%0 declared here">; +def note_defined_here : Note<"%0 defined here">; + def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; def err_atomic_builtin_must_be_pointer : Error< @@ -4031,12 +4525,15 @@ def err_atomic_builtin_pointer_size : Error< def err_atomic_op_needs_atomic : Error< "first argument to atomic operation must be a pointer to _Atomic " "type (%0 invalid)">; +def err_atomic_op_needs_trivial_copy : Error< + "first argument to atomic operation must be a pointer to a trivially-copyable" + " type (%0 invalid)">; def err_atomic_op_needs_atomic_int_or_ptr : Error< - "first argument to atomic operation must be a pointer to atomic " - "integer or pointer (%0 invalid)">; -def err_atomic_op_logical_needs_atomic_int : Error< - "first argument to logical atomic operation must be a pointer to atomic " - "integer (%0 invalid)">; + "first argument to atomic operation must be a pointer to %select{|atomic }0" + "integer or pointer (%1 invalid)">; +def err_atomic_op_bitwise_needs_atomic_int : Error< + "first argument to bitwise atomic operation must be a pointer to " + "%select{|atomic }0integer (%1 invalid)">; def err_deleted_function_use : Error<"attempt to use a deleted function">; @@ -4061,6 +4558,10 @@ def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic" " %select{function|block|method|constructor}2; call will abort at runtime">, InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; +def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning< + "passing object of trivial but non-POD type %0 through variadic" + " %select{function|block|method|constructor}1 is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_typecheck_call_invalid_ordered_compare : Error< "ordered compare requires two args of floating point type (%0 and %1)">; @@ -4101,9 +4602,6 @@ def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn< InGroup<DiagGroup<"conditional-type-mismatch">>; def err_typecheck_choose_expr_requires_constant : Error< "'__builtin_choose_expr' requires a constant expression">; -def ext_typecheck_expression_not_constant_but_accepted : Extension< - "expression is not a constant, but is accepted as one by GNU extensions">, - InGroup<GNU>; def warn_unused_expr : Warning<"expression result unused">, InGroup<UnusedValue>; def warn_unused_voidptr : Warning< @@ -4112,6 +4610,9 @@ def warn_unused_voidptr : Warning< def warn_unused_property_expr : Warning< "property access result unused - getters should not be used for side effects">, InGroup<UnusedValue>; +def warn_unused_container_subscript_expr : Warning< + "container access result unused - container access should not be used for side effects">, + InGroup<UnusedValue>; def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, InGroup<UnusedValue>; @@ -4126,6 +4627,10 @@ def note_inequality_comparison_to_or_assign : Note< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; +def err_type_trait_arity : Error< + "type trait requires %0%select{| or more}1 argument%select{|s}2; have " + "%3 argument%s3">; + def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">; @@ -4171,10 +4676,6 @@ def err_invalid_conversion_between_vector_and_integer : Error< def err_invalid_conversion_between_vector_and_scalar : Error< "invalid conversion between vector type %0 and scalar type %1">; -def err_overload_expr_requires_non_zero_constant : Error< - "overload requires a non-zero constant expression as first argument">; -def err_overload_incorrect_fntype : Error< - "argument is not a function, or has wrong number of parameters">; // C++ member initializers. def err_only_constructors_take_base_inits : Error< @@ -4183,7 +4684,7 @@ def err_only_constructors_take_base_inits : Error< def err_multiple_mem_initialization : Error < "multiple initializations given for non-static member %0">; def err_multiple_mem_union_initialization : Error < - "initializing multiple members of anonymous union">; + "initializing multiple members of union">; def err_multiple_base_initialization : Error < "multiple initializations given for base %0">; @@ -4219,16 +4720,19 @@ def err_in_class_initializer_literal_type : Error< "in-class initializer for static data member of type %0 requires " "'constexpr' specifier">; def err_in_class_initializer_non_constant : Error< - "in-class initializer is not a constant expression">; + "in-class initializer for static data member is not a constant expression">; def ext_in_class_initializer_non_constant : Extension< - "in-class initializer is not a constant expression, accepted as an extension">; + "in-class initializer for static data member is not a constant expression; " + "folding it to a constant is a GNU extension">; // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< - "anonymous unions are a GNU extension in C">, InGroup<GNU>; -def ext_anonymous_struct : Extension< + "anonymous unions are a C11 extension">, InGroup<C11>; +def ext_gnu_anonymous_struct : Extension< "anonymous structs are a GNU extension">, InGroup<GNU>; +def ext_c11_anonymous_struct : Extension< + "anonymous structs are a C11 extension">, InGroup<C11>; def err_anonymous_union_not_static : Error< "anonymous unions at namespace or global scope must be declared 'static'">; def err_anonymous_union_with_storage_spec : Error< @@ -4259,7 +4763,14 @@ def ext_ms_anonymous_struct : ExtWarn< // C++ local classes def err_reference_to_local_var_in_enclosing_function : Error< - "reference to local variable %0 declared in enclosed function %1">; + "reference to local variable %0 declared in enclosing function %1">; +def err_reference_to_local_var_in_enclosing_block : Error< + "reference to local variable %0 declared in enclosing block literal">; +def err_reference_to_local_var_in_enclosing_lambda : Error< + "reference to local variable %0 declared in enclosing lambda expression">; +def err_reference_to_local_var_in_enclosing_context : Error< + "reference to local variable %0 declared in enclosing context">; + def note_local_variable_declared_here : Note< "%0 declared here">; def err_static_data_member_not_allowed_in_local_class : Error< @@ -4283,14 +4794,6 @@ def err_memptr_conv_via_virtual : Error< "conversion from pointer to member of class %0 to pointer to member " "of class %1 via virtual base %2 is not allowed">; -// C++ access control -def err_conv_to_inaccessible_base : Error< - "conversion from %0 to inaccessible base class %1">, AccessControl; -def note_inheritance_specifier_here : Note< - "'%0' inheritance specifier here">; -def note_inheritance_implicitly_private_here : Note< - "inheritance is implicitly 'private'">; - // C++ member name lookup def err_ambiguous_member_multiple_subobjects : Error< "non-static member %0 found in multiple base-class subobjects of type %1:%2">; @@ -4353,16 +4856,18 @@ def err_operator_delete_param_type : Error< // C++ literal operators def err_literal_operator_outside_namespace : Error< "literal operator %0 must be in a namespace or global scope">; +def err_literal_operator_default_argument : Error< + "literal operator cannot have a default argument">; // FIXME: This diagnostic sucks def err_literal_operator_params : Error< "parameter declaration for literal operator %0 is not valid">; -def warn_user_literal_hexfloat : Warning< - "user-defined literal with suffix '%0' is preempted by C99 hexfloat " - "extension">, InGroup<UserDefinedLiterals>; +def err_literal_operator_extern_c : Error< + "literal operator must have C++ linkage">; def warn_user_literal_reserved : Warning< - "user-defined literals not starting with '_' are reserved by the " - "implementation">, InGroup<UserDefinedLiterals>; - + "user-defined literal suffixes not starting with '_' are reserved; " + "no literal will invoke this operator">, + InGroup<UserDefinedLiterals>; + // C++ conversion functions def err_conv_function_not_member : Error< "conversion function must be a non-static member function">; @@ -4391,8 +4896,11 @@ def warn_not_compound_assign : Warning< "use of unary operator that may be intended as compound assignment (%0=)">; // C++11 explicit conversion operators -def warn_explicit_conversion_functions : Warning< +def ext_explicit_conversion_functions : ExtWarn< "explicit conversion functions are a C++11 extension">, InGroup<CXX11>; +def warn_cxx98_compat_explicit_conversion_functions : Warning< + "explicit conversion functions are incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; // C++11 defaulted functions def err_defaulted_default_ctor_params : Error< @@ -4454,6 +4962,9 @@ def err_incorrect_defaulted_exception_spec : Error< "copy constructor|move constructor|copy assignment operator|move assignment " "operator|destructor}0 does not match the " "calculated one">; +def err_incorrect_defaulted_constexpr : Error< + "defaulted definition of %select{default constructor|copy constructor|" + "move constructor}0 is not constexpr">; def err_out_of_line_default_deletes : Error< "defaulting this %select{default constructor|copy constructor|move " "constructor|copy assignment operator|move assignment operator|destructor}0 " @@ -4467,10 +4978,10 @@ def warn_ptr_arith_exceeds_bounds : Warning< "contains %1 element%s2)">, InGroup<DiagGroup<"array-bounds-pointer-arithmetic">>, DefaultIgnore; def warn_array_index_precedes_bounds : Warning< - "array index of '%0' indexes before the beginning of the array">, + "array index %0 is before the beginning of the array">, InGroup<DiagGroup<"array-bounds">>; def warn_array_index_exceeds_bounds : Warning< - "array index of '%0' indexes past the end of an array (that contains %1 " + "array index %0 is past the end of the array (which contains %1 " "element%s2)">, InGroup<DiagGroup<"array-bounds">>; def note_array_index_out_of_bounds : Note< "array %0 declared here">; @@ -4492,7 +5003,7 @@ def warn_scanf_nonzero_width : Warning< "zero field width in scanf format string is unused">, InGroup<Format>; def warn_printf_conversion_argument_type_mismatch : Warning< - "conversion specifies type %0 but the argument has type %1">, + "format specifies type %0 but the argument has type %1">, InGroup<Format>; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, @@ -4506,9 +5017,11 @@ def warn_format_invalid_positional_specifier : Warning< def warn_format_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>; +def warn_static_array_too_small : Warning< + "array argument is too small; contains %0 elements, callee requires at least %1">, + InGroup<DiagGroup<"array-bounds">>; +def note_callee_static_array : Note< + "callee declares array parameter as static here">; def warn_empty_format_string : Warning< "format string is empty">, InGroup<FormatZeroLength>; def warn_format_string_is_wide_literal : Warning< @@ -4529,13 +5042,26 @@ def warn_printf_nonsensical_flag: Warning< def warn_format_nonsensical_length: Warning< "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, InGroup<Format>; +def warn_format_non_standard_positional_arg: ExtWarn< + "positional arguments are not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore; +def warn_format_non_standard: ExtWarn< + "'%0' %select{length modifier|conversion specifier}1 is not supported by ISO C">, + InGroup<FormatNonStandard>, DefaultIgnore; +def warn_format_non_standard_conversion_spec: ExtWarn< + "using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">, + InGroup<FormatNonStandard>, DefaultIgnore; def warn_printf_ignored_flag: Warning< "flag '%0' is ignored when flag '%1' is present">, InGroup<Format>; def warn_scanf_scanlist_incomplete : Warning< "no closing ']' for '%%[' in scanf format string">, InGroup<Format>; - +def note_format_string_defined : Note<"format string is defined here">; + +def warn_null_arg : Warning< + "null passed to a callee which requires a non-null argument">, + InGroup<NonNull>; + // CHECK: returning address/reference of stack memory def warn_ret_stack_addr : Warning< "address of stack memory associated with local variable %0 returned">, @@ -4603,9 +5129,6 @@ def err_generic_sel_multi_match : Error< // Blocks def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" " or pick a deployment target that supports them">; -def err_expected_block_lbrace : Error<"expected '{' in block literal">; -def err_return_in_block_expression : Error< - "return not allowed in block expression literal">; def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; @@ -4639,20 +5162,37 @@ def err_duplicate_case : Error<"duplicate case value '%0'">; def warn_case_empty_range : Warning<"empty case range specified">; def warn_missing_case_for_condition : Warning<"no case matching constant switch condition '%0'">; + +def warn_def_missing_case1 : Warning< + "enumeration value %0 not explicitly handled in switch">, + InGroup<SwitchEnum>, DefaultIgnore; +def warn_def_missing_case2 : Warning< + "enumeration values %0 and %1 not explicitly handled in switch">, + InGroup<SwitchEnum>, DefaultIgnore; +def warn_def_missing_case3 : Warning< + "enumeration values %0, %1, and %2 not explicitly handled in switch">, + InGroup<SwitchEnum>, DefaultIgnore; +def warn_def_missing_cases : Warning< + "%0 enumeration values not explicitly handled in switch: %1, %2, %3...">, + InGroup<SwitchEnum>, DefaultIgnore; + def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">, - InGroup<DiagGroup<"switch-enum"> >; + InGroup<Switch>; def warn_missing_case2 : Warning< "enumeration values %0 and %1 not handled in switch">, - InGroup<DiagGroup<"switch-enum"> >; + InGroup<Switch>; def warn_missing_case3 : Warning< "enumeration values %0, %1, and %2 not handled in switch">, - InGroup<DiagGroup<"switch-enum"> >; + InGroup<Switch>; def warn_missing_cases : Warning< "%0 enumeration values not handled in switch: %1, %2, %3...">, - InGroup<DiagGroup<"switch-enum"> >; + InGroup<Switch>; +def warn_unreachable_default : Warning< + "default label in switch which covers all enumeration values">, + InGroup<CoveredSwitchDefault>, DefaultIgnore; def warn_not_in_enum : Warning<"case value not in enumerated type %0">, - InGroup<DiagGroup<"switch-enum"> >; + InGroup<Switch>; def err_typecheck_statement_requires_scalar : Error< "statement requires expression of scalar type (%0 invalid)">; def err_typecheck_statement_requires_integer : Error< @@ -4668,8 +5208,20 @@ def err_switch_explicit_conversion : Error< "switch condition type %0 requires explicit conversion to %1">; def err_switch_incomplete_class_type : Error< "switch condition has incomplete class type %0">; + def warn_empty_if_body : Warning< "if statement has empty body">, InGroup<EmptyBody>; +def warn_empty_for_body : Warning< + "for loop has empty body">, InGroup<EmptyBody>; +def warn_empty_range_based_for_body : Warning< + "range-based for loop has empty body">, InGroup<EmptyBody>; +def warn_empty_while_body : Warning< + "while loop has empty body">, InGroup<EmptyBody>; +def warn_empty_switch_body : Warning< + "switch statement has empty body">, InGroup<EmptyBody>; +def note_empty_body_on_separate_line : Note< + "put the semicolon on a separate line to silence this warning">, + InGroup<EmptyBody>; def err_va_start_used_in_non_variadic_function : Error< "'va_start' used in function with fixed args">; @@ -4702,7 +5254,10 @@ def ext_return_has_expr : ExtWarn< "should not return a value">, DefaultError, InGroup<ReturnType>; def ext_return_has_void_expr : Extension< - "void %select{function|method}1 %0 should not return void expression">; + "void %select{function|method|block}1 %0 should not return void expression">; +def err_return_init_list : Error< + "%select{void function|void method|constructor|destructor}1 %0 " + "must not return a value">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup<DiagGroup<"invalid-noreturn">>; @@ -4775,14 +5330,14 @@ def err_decimal_unsupported : Error< "GNU decimal type extension not supported">; def err_missing_type_specifier : Error< "C++ requires a type specifier for all declarations">; -def err_missing_param_declspec : Error< - "parameter requires a declaration specifier">; def err_objc_array_of_interfaces : Error< "array of interface %0 is invalid (probably should be an array of pointers)">; def ext_c99_array_usage : Extension< - "use of C99-specific array features, accepted as an extension">; + "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 " + "feature">, InGroup<C99>; def err_c99_array_usage_cxx : Error< - "C99-specific array features are not permitted in C++">; + "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 " + "feature, not permitted in C++">; def err_double_requires_fp64 : Error< "use of type 'double' requires cl_khr_fp64 extension to be enabled">; def err_nsconsumed_attribute_mismatch : Error< @@ -4809,7 +5364,8 @@ def error_protected_ivar_access : Error<"instance variable %0 is protected">, AccessControl; def warn_maynot_respond : Warning<"%0 may not respond to %1">; def warn_attribute_method_def : Warning< - "method attribute can only be specified on method declarations">; + "attributes on method implementation and its declaration must match">, + InGroup<DiagGroup<"mismatched-method-attributes">>; def ext_typecheck_base_super : Warning< "method parameter type %0 does not match " "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore; @@ -4916,8 +5472,6 @@ def note_related_result_type_inferred : Note< } let CategoryName = "Modules Issue" in { -def err_module_private_follows_public : Error< - "__module_private__ declaration of %0 follows public declaration">; def err_module_private_specialization : Error< "%select{template|partial|member}0 specialization cannot be " "declared __module_private__">; @@ -4927,6 +5481,8 @@ def err_module_private_local : Error< def err_module_private_local_class : Error< "local %select{struct|union|class|enum}0 cannot be declared " "__module_private__">; +def err_module_private_definition : Error< + "definition of %0 must be imported before it is required">; } } // end of sema component. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td new file mode 100644 index 0000000..7f9fe26 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -0,0 +1,60 @@ +//==--- DiagnosticSerializationKinds.td - serialization diagnostics -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "Serialization" in { + +def err_fe_unable_to_read_pch_file : Error< + "unable to read PCH file: '%0'">; +def err_fe_not_a_pch_file : Error< + "input is not a PCH file: '%0'">; +def err_fe_pch_malformed : Error< + "malformed or corrupted PCH file: '%0'">, DefaultFatal; +def err_fe_pch_malformed_block : Error< + "malformed block record in PCH file: '%0'">, DefaultFatal; +def err_fe_pch_error_at_end_block : Error< + "error at end of module block in PCH file: '%0'">, DefaultFatal; +def err_fe_pch_file_modified : Error< + "file '%0' has been modified since the precompiled header was built">, + DefaultFatal; + +def warn_pch_target_triple : Error< + "PCH file was compiled for the target '%0' but the current translation " + "unit is being compiled for target '%1'">; +def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " + "PCH file but is currently %select{disabled|enabled}2">; +def err_pch_langopt_value_mismatch : Error< + "%0 differs in PCH file vs. current file">; + +def warn_pch_version_too_old : Error< + "PCH file uses an older PCH format that is no longer supported">; +def warn_pch_version_too_new : Error< + "PCH file uses a newer PCH format that cannot be read">; +def warn_pch_different_branch : Error< + "PCH file built from a different branch (%0) than the compiler (%1)">; +def err_pch_with_compiler_errors : Error< + "PCH file contains compiler errors">; +def warn_cmdline_conflicting_macro_def : Error< + "definition of the macro '%0' conflicts with the definition used to " + "build the precompiled header">; +def note_pch_macro_defined_as : Note< + "definition of macro '%0' in the precompiled header">; +def warn_cmdline_missing_macro_defs : Warning< + "macro definitions used to build the precompiled header are missing">; +def note_using_macro_def_from_pch : Note< + "using this macro definition from precompiled header">; +def warn_macro_name_used_in_pch : Error< + "definition of macro %0 conflicts with an identifier used in the " + "precompiled header">; +def warn_pch_compiler_options_mismatch : Error< + "compiler options used when building the precompiled header differ from " + "the options used when using the precompiled header">; + +def err_not_a_pch_file : Error< + "'%0' does not appear to be a precompiled header file">, DefaultFatal; +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h index 403a59a..c4e6a1c 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h @@ -1,4 +1,4 @@ -//===--- ExpressionTraits.h - C++ Expression Traits Support Enumerations ----*- C++ -*-===// +//===- ExpressionTraits.h - C++ Expression Traits Support Enums -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h index ea8ed9f..5c7d9eb 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h @@ -39,7 +39,7 @@ namespace sys { class Path; } namespace clang { class FileManager; class FileSystemStatCache; - + /// DirectoryEntry - Cached information about one directory (either on /// the disk or in the virtual file system). /// @@ -64,12 +64,12 @@ class FileEntry { dev_t Device; // ID for the device containing the file. ino_t Inode; // Inode number for the file. mode_t FileMode; // The file mode as returned by 'stat'. - + /// FD - The file descriptor for the file entry if it is opened and owned /// by the FileEntry. If not, this is set to -1. mutable int FD; friend class FileManager; - + public: FileEntry(dev_t device, ino_t inode, mode_t m) : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {} @@ -80,7 +80,7 @@ public: memcpy(this, &FE, sizeof(FE)); assert(FD == -1 && "Cannot copy a file-owning FileEntry"); } - + void operator=(const FileEntry &FE) { memcpy(this, &FE, sizeof(FE)); assert(FD == -1 && "Cannot assign a file-owning FileEntry"); @@ -110,13 +110,14 @@ public: /// properties, such as uniquing files based on "inode", so that a file with two /// names (e.g. symlinked) will be treated as a single file. /// -class FileManager : public llvm::RefCountedBase<FileManager> { +class FileManager : public RefCountedBase<FileManager> { FileSystemOptions FileSystemOpts; class UniqueDirContainer; class UniqueFileContainer; - /// UniqueRealDirs/UniqueRealFiles - Cache for existing real directories/files. + /// UniqueRealDirs/UniqueRealFiles - Cache for existing real + /// directories/files. /// UniqueDirContainer &UniqueRealDirs; UniqueFileContainer &UniqueRealFiles; @@ -147,7 +148,7 @@ class FileManager : public llvm::RefCountedBase<FileManager> { unsigned NumDirCacheMisses, NumFileCacheMisses; // Caching. - llvm::OwningPtr<FileSystemStatCache> StatCache; + OwningPtr<FileSystemStatCache> StatCache; bool getStatValue(const char *Path, struct stat &StatBuf, int *FileDescriptor); @@ -224,7 +225,7 @@ public: /// file to the corresponding FileEntry pointer. void GetUniqueIDMapping( SmallVectorImpl<const FileEntry *> &UIDToFiles) const; - + void PrintStats() const; }; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h index 77828b3..96a2f90 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H #define LLVM_CLANG_FILESYSTEMSTATCACHE_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include <sys/types.h> @@ -25,8 +26,9 @@ namespace clang { /// system calls, which is used by precompiled and pretokenized headers to /// improve performance. class FileSystemStatCache { + virtual void anchor(); protected: - llvm::OwningPtr<FileSystemStatCache> NextStatCache; + OwningPtr<FileSystemStatCache> NextStatCache; public: virtual ~FileSystemStatCache() {} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h index 5e48a86..cc0080b 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h @@ -20,11 +20,9 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> -#include <cctype> #include <string> namespace llvm { @@ -49,8 +47,6 @@ namespace clang { /// variable or function name). The preprocessor keeps this information in a /// set, and all tok::identifier tokens have a pointer to one of these. class IdentifierInfo { - // Note: DON'T make TokenID a 'tok::TokenKind'; MSVC will treat it as a - // signed char and TokenKinds > 255 won't be handled correctly. unsigned TokenID : 9; // Front-end token ID or tok::identifier. // Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf). // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values @@ -62,11 +58,19 @@ class IdentifierInfo { bool IsPoisoned : 1; // True if identifier is poisoned. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". - bool IsFromAST : 1; // True if identfier first appeared in an AST - // file and wasn't modified since. + bool IsFromAST : 1; // True if identifier was loaded (at least + // partially) from an AST file. + bool ChangedAfterLoad : 1; // True if identifier has changed from the + // definition loaded from an AST file. bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was // called. - // 5 bits left in 32-bit word. + bool OutOfDate : 1; // True if there may be additional + // information about this identifier + // stored externally. + bool IsModulesImport : 1; // True if this is the 'import' contextual + // keyword. + // 1 bit left in 32-bit word. + void *FETokenInfo; // Managed by the language front-end. llvm::StringMapEntry<IdentifierInfo*> *Entry; @@ -132,7 +136,6 @@ public: NeedsHandleIdentifier = 1; else RecomputeNeedsHandleIdentifier(); - IsFromAST = false; } /// getTokenID - If this is a source-language token (e.g. 'for'), this API @@ -221,7 +224,6 @@ public: NeedsHandleIdentifier = 1; else RecomputeNeedsHandleIdentifier(); - IsFromAST = false; } /// isPoisoned - Return true if this token has been poisoned. @@ -253,8 +255,48 @@ public: /// from an AST file. bool isFromAST() const { return IsFromAST; } - void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; } + void setIsFromAST() { IsFromAST = true; } + /// \brief Determine whether this identifier has changed since it was loaded + /// from an AST file. + bool hasChangedSinceDeserialization() const { + return ChangedAfterLoad; + } + + /// \brief Note that this identifier has changed since it was loaded from + /// an AST file. + void setChangedSinceDeserialization() { + ChangedAfterLoad = true; + } + + /// \brief Determine whether the information for this identifier is out of + /// date with respect to the external source. + bool isOutOfDate() const { return OutOfDate; } + + /// \brief Set whether the information for this identifier is out of + /// date with respect to the external source. + void setOutOfDate(bool OOD) { + OutOfDate = OOD; + if (OOD) + NeedsHandleIdentifier = true; + else + RecomputeNeedsHandleIdentifier(); + } + + /// \brief Determine whether this is the contextual keyword + /// '__experimental_modules_import'. + bool isModulesImport() const { return IsModulesImport; } + + /// \brief Set whether this identifier is the contextual keyword + /// '__experimental_modules_import'. + void setModulesImport(bool I) { + IsModulesImport = I; + if (I) + NeedsHandleIdentifier = true; + else + RecomputeNeedsHandleIdentifier(); + } + private: /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does /// several special (but rare) things to identifiers of various sorts. For @@ -266,8 +308,8 @@ private: void RecomputeNeedsHandleIdentifier() { NeedsHandleIdentifier = (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() | - isExtensionToken() | isCXX11CompatKeyword() || - (getTokenID() == tok::kw___import_module__)); + isExtensionToken() | isCXX11CompatKeyword() || isOutOfDate() || + isModulesImport()); } }; @@ -449,6 +491,10 @@ public: // Make sure getName() knows how to find the IdentifierInfo // contents. II->Entry = &Entry; + + // If this is the 'import' contextual keyword, mark it as such. + if (Name.equals("import")) + II->setModulesImport(true); } return *II; @@ -662,14 +708,7 @@ public: /// has been capitalized. static Selector constructSetterName(IdentifierTable &Idents, SelectorTable &SelTable, - const IdentifierInfo *Name) { - llvm::SmallString<100> SelectorName; - SelectorName = "set"; - SelectorName += Name->getName(); - SelectorName[3] = toupper(SelectorName[3]); - IdentifierInfo *SetterName = &Idents.get(SelectorName); - return SelTable.getUnarySelector(SetterName); - } + const IdentifierInfo *Name); }; /// DeclarationNameExtra - Common base of the MultiKeywordSelector, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h index 27c459d..813b49e 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h @@ -24,9 +24,20 @@ namespace llvm { class StringRef; class Twine; template<typename T> class ArrayRef; + template<class T> class OwningPtr; + template<unsigned InternalLen> class SmallString; template<typename T, unsigned N> class SmallVector; template<typename T> class SmallVectorImpl; + template<typename T> + struct SaveAndRestore; + + // Reference counting. + template <typename T> class IntrusiveRefCntPtr; + template <typename T> struct IntrusiveRefCntPtrInfo; + template <class Derived> class RefCountedBase; + class RefCountedBaseVPTR; + class raw_ostream; // TODO: DenseMap, ... } @@ -44,9 +55,18 @@ namespace clang { using llvm::StringRef; using llvm::Twine; using llvm::ArrayRef; + using llvm::OwningPtr; + using llvm::SmallString; using llvm::SmallVector; using llvm::SmallVectorImpl; - + using llvm::SaveAndRestore; + + // Reference counting. + using llvm::IntrusiveRefCntPtr; + using llvm::IntrusiveRefCntPtrInfo; + using llvm::RefCountedBase; + using llvm::RefCountedBaseVPTR; + using llvm::raw_ostream; } // end namespace clang. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h new file mode 100644 index 0000000..df50d94 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h @@ -0,0 +1,38 @@ +//===--- Lambda.h - Types for C++ Lambdas -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines several types used to describe C++ lambda +// expressions that are shared between the parser and AST. +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_BASIC_LAMBDA_H +#define LLVM_CLANG_BASIC_LAMBDA_H + +namespace clang { + +/// LambdaCaptureDefault - The default, if any, capture method for a +/// lambda expression. +enum LambdaCaptureDefault { + LCD_None, + LCD_ByCopy, + LCD_ByRef +}; + +/// LambdaCaptureKind - The different capture forms in a lambda +/// introducer: 'this' or a copied or referenced variable. +enum LambdaCaptureKind { + LCK_This, + LCK_ByCopy, + LCK_ByRef +}; + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_LAMBDA_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def index c8389ab..786ae12 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def @@ -42,7 +42,7 @@ #endif LANGOPT(C99 , 1, 0, "C99") -LANGOPT(C1X , 1, 0, "C1X") +LANGOPT(C11 , 1, 0, "C11") LANGOPT(MicrosoftExt , 1, 0, "Microsoft extensions") LANGOPT(MicrosoftMode , 1, 0, "Microsoft compatibility mode") LANGOPT(Borland , 1, 0, "Borland extensions") @@ -91,16 +91,18 @@ LANGOPT(Blocks , 1, 0, "blocks extension to C") BENIGN_LANGOPT(EmitAllDecls , 1, 0, "support for emitting all declarations") LANGOPT(MathErrno , 1, 1, "errno support for math functions") BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time") - +LANGOPT(Modules , 1, 0, "modules extension to C") LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") VALUE_LANGOPT(PackStruct , 32, 0, "default struct packing maximum alignment") -VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") +VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") +VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level") LANGOPT(GNUInline , 1, 0, "GNU inline semantics") -LANGOPT(NoInline , 1, 0, "__NO_INLINE__ predefined macro") +LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") +LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") @@ -117,17 +119,23 @@ LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++' BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") BENIGN_LANGOPT(CatchUndefined , 1, 0, "catching undefined behavior at run time") BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records") +BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form") BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables") LANGOPT(NoConstantCFStrings , 1, 0, "no constant CoreFoundation strings") BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inline C++ methods") BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") +BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") +BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger objective-C literals and subscripting support") +BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled") +BENIGN_LANGOPT(ThreadSanitizer , 1, 0, "ThreadSanitizer enabled") BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") +LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") LANGOPT(ObjCRuntimeHasWeak , 1, 0, "__weak support in the ARC runtime") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") @@ -146,11 +154,15 @@ ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, BENIGN_LANGOPT(InstantiationDepth, 32, 1024, "maximum template instantiation depth") +BENIGN_LANGOPT(ConstexprCallDepth, 32, 512, + "maximum constexpr call depth") BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0, "if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.") VALUE_LANGOPT(MSCVersion, 32, 0, "version of Microsoft Visual C/C++") +LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") + #undef LANGOPT #undef VALUE_LANGOPT #undef BENIGN_LANGOPT diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h index 688047f..ce4ff06 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h @@ -15,13 +15,33 @@ #define LLVM_CLANG_LANGOPTIONS_H #include <string> +#include "clang/Basic/LLVM.h" #include "clang/Basic/Visibility.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" namespace clang { +/// Bitfields of LangOptions, split out from LangOptions in order to ensure that +/// this large collection of bitfields is a trivial class type. +class LangOptionsBase { +public: + // Define simple language options (with no accessors). +#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#include "clang/Basic/LangOptions.def" + +protected: + // Define language options of enumeration type. These are private, and will + // have accessors (below). +#define LANGOPT(Name, Bits, Default, Description) +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + unsigned Name : Bits; +#include "clang/Basic/LangOptions.def" +}; + /// LangOptions - This class keeps track of the various options that can be /// enabled, which controls the dialect of C that is accepted. -class LangOptions { +class LangOptions : public RefCountedBase<LangOptions>, public LangOptionsBase { public: typedef clang::Visibility Visibility; @@ -34,19 +54,6 @@ public: SOB_Trapping // -ftrapv }; - // Define simple language options (with no accessors). -#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) -#include "clang/Basic/LangOptions.def" - -private: - // Define language options of enumeration type. These are private, and will - // have accessors (below). -#define LANGOPT(Name, Bits, Default, Description) -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - unsigned Name : Bits; -#include "clang/Basic/LangOptions.def" - public: std::string ObjCConstantStringClass; @@ -54,6 +61,9 @@ public: /// If none is specified, abort (GCC-compatible behaviour). std::string OverflowHandler; + /// \brief The name of the current module. + std::string CurrentModule; + LangOptions(); // Define accessors/mutators for language options of enumeration type. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h index 01b6c79..09a5a0b 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h @@ -29,7 +29,7 @@ enum Linkage { InternalLinkage, /// \brief External linkage within a unique namespace. From the - /// langauge perspective, these entities have external + /// language perspective, these entities have external /// linkage. However, since they reside in an anonymous namespace, /// their names are unique to this translation unit, which is /// equivalent to having internal linkage from the code-generation diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h new file mode 100644 index 0000000..82dbd5b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h @@ -0,0 +1,284 @@ +//===--- Module.h - Describe a module ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Module class, which describes a module in the source +// code. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_MODULE_H +#define LLVM_CLANG_BASIC_MODULE_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class DirectoryEntry; +class FileEntry; +class LangOptions; +class TargetInfo; + +/// \brief Describes the name of a module. +typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> + ModuleId; + +/// \brief Describes a module or submodule. +class Module { +public: + /// \brief The name of this module. + std::string Name; + + /// \brief The location of the module definition. + SourceLocation DefinitionLoc; + + /// \brief The parent of this module. This will be NULL for the top-level + /// module. + Module *Parent; + + /// \brief The umbrella header or directory. + llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella; + +private: + /// \brief The submodules of this module, indexed by name. + std::vector<Module *> SubModules; + + /// \brief A mapping from the submodule name to the index into the + /// \c SubModules vector at which that submodule resides. + llvm::StringMap<unsigned> SubModuleIndex; + +public: + /// \brief The headers that are part of this module. + llvm::SmallVector<const FileEntry *, 2> Headers; + + /// \brief The set of language features required to use this module. + /// + /// If any of these features is not present, the \c IsAvailable bit + /// will be false to indicate that this (sub)module is not + /// available. + llvm::SmallVector<std::string, 2> Requires; + + /// \brief Whether this module is available in the current + /// translation unit. + unsigned IsAvailable : 1; + + /// \brief Whether this module was loaded from a module file. + unsigned IsFromModuleFile : 1; + + /// \brief Whether this is a framework module. + unsigned IsFramework : 1; + + /// \brief Whether this is an explicit submodule. + unsigned IsExplicit : 1; + + /// \brief Whether this is a "system" module (which assumes that all + /// headers in it are system headers). + unsigned IsSystem : 1; + + /// \brief Whether we should infer submodules for this module based on + /// the headers. + /// + /// Submodules can only be inferred for modules with an umbrella header. + unsigned InferSubmodules : 1; + + /// \brief Whether, when inferring submodules, the inferred submodules + /// should be explicit. + unsigned InferExplicitSubmodules : 1; + + /// \brief Whether, when inferring submodules, the inferr submodules should + /// export all modules they import (e.g., the equivalent of "export *"). + unsigned InferExportWildcard : 1; + + /// \brief Describes the visibility of the various names within a + /// particular module. + enum NameVisibilityKind { + /// \brief All of the names in this module are hidden. + /// + Hidden, + /// \brief Only the macro names in this module are visible. + MacrosVisible, + /// \brief All of the names in this module are visible. + AllVisible + }; + + ///\ brief The visibility of names within this particular module. + NameVisibilityKind NameVisibility; + + /// \brief The location of the inferred submodule. + SourceLocation InferredSubmoduleLoc; + + /// \brief The set of modules imported by this module, and on which this + /// module depends. + llvm::SmallVector<Module *, 2> Imports; + + /// \brief Describes an exported module. + /// + /// The pointer is the module being re-exported, while the bit will be true + /// to indicate that this is a wildcard export. + typedef llvm::PointerIntPair<Module *, 1, bool> ExportDecl; + + /// \brief The set of export declarations. + llvm::SmallVector<ExportDecl, 2> Exports; + + /// \brief Describes an exported module that has not yet been resolved + /// (perhaps because tASThe module it refers to has not yet been loaded). + struct UnresolvedExportDecl { + /// \brief The location of the 'export' keyword in the module map file. + SourceLocation ExportLoc; + + /// \brief The name of the module. + ModuleId Id; + + /// \brief Whether this export declaration ends in a wildcard, indicating + /// that all of its submodules should be exported (rather than the named + /// module itself). + bool Wildcard; + }; + + /// \brief The set of export declarations that have yet to be resolved. + llvm::SmallVector<UnresolvedExportDecl, 2> UnresolvedExports; + + /// \brief Construct a top-level module. + explicit Module(StringRef Name, SourceLocation DefinitionLoc, + bool IsFramework) + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(), + IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), + IsExplicit(false), IsSystem(false), + InferSubmodules(false), InferExplicitSubmodules(false), + InferExportWildcard(false), NameVisibility(Hidden) { } + + /// \brief Construct a new module or submodule. + Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, + bool IsFramework, bool IsExplicit); + + ~Module(); + + /// \brief Determine whether this module is available for use within the + /// current translation unit. + bool isAvailable() const { return IsAvailable; } + + /// \brief Determine whether this module is available for use within the + /// current translation unit. + /// + /// \param LangOpts The language options used for the current + /// translation unit. + /// + /// \param Target The target options used for the current translation unit. + /// + /// \param Feature If this module is unavailable, this parameter + /// will be set to one of the features that is required for use of + /// this module (but is not available). + bool isAvailable(const LangOptions &LangOpts, + const TargetInfo &Target, + StringRef &Feature) const; + + /// \brief Determine whether this module is a submodule. + bool isSubModule() const { return Parent != 0; } + + /// \brief Determine whether this module is a submodule of the given other + /// module. + bool isSubModuleOf(Module *Other) const; + + /// \brief Determine whether this module is a part of a framework, + /// either because it is a framework module or because it is a submodule + /// of a framework module. + bool isPartOfFramework() const { + for (const Module *Mod = this; Mod; Mod = Mod->Parent) + if (Mod->IsFramework) + return true; + + return false; + } + + /// \brief Retrieve the full name of this module, including the path from + /// its top-level module. + std::string getFullModuleName() const; + + /// \brief Retrieve the top-level module for this (sub)module, which may + /// be this module. + Module *getTopLevelModule() { + return const_cast<Module *>( + const_cast<const Module *>(this)->getTopLevelModule()); + } + + /// \brief Retrieve the top-level module for this (sub)module, which may + /// be this module. + const Module *getTopLevelModule() const; + + /// \brief Retrieve the name of the top-level module. + /// + StringRef getTopLevelModuleName() const { + return getTopLevelModule()->Name; + } + + /// \brief Retrieve the directory for which this module serves as the + /// umbrella. + const DirectoryEntry *getUmbrellaDir() const; + + /// \brief Retrieve the header that serves as the umbrella header for this + /// module. + const FileEntry *getUmbrellaHeader() const { + return Umbrella.dyn_cast<const FileEntry *>(); + } + + /// \brief Determine whether this module has an umbrella directory that is + /// not based on an umbrella header. + bool hasUmbrellaDir() const { + return Umbrella && Umbrella.is<const DirectoryEntry *>(); + } + + /// \briaf Add the given feature requirement to the list of features + /// required by this module. + /// + /// \param Feature The feature that is required by this module (and + /// its submodules). + /// + /// \param LangOpts The set of language options that will be used to + /// evaluate the availability of this feature. + /// + /// \param Target The target options that will be used to evaluate the + /// availability of this feature. + void addRequirement(StringRef Feature, const LangOptions &LangOpts, + const TargetInfo &Target); + + /// \brief Find the submodule with the given name. + /// + /// \returns The submodule if found, or NULL otherwise. + Module *findSubmodule(StringRef Name) const; + + typedef std::vector<Module *>::iterator submodule_iterator; + typedef std::vector<Module *>::const_iterator submodule_const_iterator; + + submodule_iterator submodule_begin() { return SubModules.begin(); } + submodule_const_iterator submodule_begin() const {return SubModules.begin();} + submodule_iterator submodule_end() { return SubModules.end(); } + submodule_const_iterator submodule_end() const { return SubModules.end(); } + + /// \brief Print the module map for this module to the given stream. + /// + void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; + + /// \brief Dump the contents of this module to the given output stream. + void dump() const; +}; + +} // end namespace clang + + +#endif // LLVM_CLANG_BASIC_MODULE_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h index 7328b1a..8028a73 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h @@ -356,7 +356,7 @@ public: friend bool operator!=(const key_iterator& X, const key_iterator &Y) { return X.NumEntriesLeft != Y.NumEntriesLeft; } - + key_iterator& operator++() { // Preincrement if (!NumItemsInBucketLeft) { // 'Items' starts with a 16-bit unsigned integer representing the @@ -421,7 +421,7 @@ public: bool operator!=(const item_iterator& X) const { return X.NumEntriesLeft != NumEntriesLeft; } - + item_iterator& operator++() { // Preincrement if (!NumItemsInBucketLeft) { // 'Items' starts with a 16-bit unsigned integer representing the @@ -449,7 +449,7 @@ public: LocalPtr += 4; // Skip the hash. // Determine the length of the key and the data. - const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr); + const std::pair<unsigned, unsigned>& L =Info::ReadKeyDataLength(LocalPtr); // Read the key. const internal_key_type& Key = @@ -458,14 +458,14 @@ public: InfoObj->ReadData(Key, LocalPtr + L.first, L.second)); } }; - + item_iterator item_begin() { return item_iterator(Base + 4, getNumEntries(), &InfoObj); } item_iterator item_end() { return item_iterator(); } Info &getInfoObj() { return InfoObj; } - + static OnDiskChainedHashTable* Create(const unsigned char* buckets, const unsigned char* const base, const Info &InfoObj = Info()) { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h index c6ca989..007e6a4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h @@ -25,88 +25,90 @@ namespace clang { class PartialDiagnostic { public: + enum { + // The MaxArguments and MaxFixItHints member enum values from + // DiagnosticsEngine are private but DiagnosticsEngine declares + // PartialDiagnostic a friend. These enum values are redeclared + // here so that the nested Storage class below can access them. + MaxArguments = DiagnosticsEngine::MaxArguments + }; + struct Storage { - Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { } + Storage() : NumDiagArgs(0), NumDiagRanges(0) { } enum { - /// MaxArguments - The maximum number of arguments we can hold. We + /// MaxArguments - The maximum number of arguments we can hold. We /// currently only support up to 10 arguments (%0-%9). /// A single diagnostic with more than that almost certainly has to /// be simplified anyway. - MaxArguments = DiagnosticsEngine::MaxArguments + MaxArguments = PartialDiagnostic::MaxArguments }; - + /// NumDiagArgs - This contains the number of entries in Arguments. unsigned char NumDiagArgs; - + /// NumDiagRanges - This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; - /// \brief The number of code modifications hints in the - /// FixItHints array. - unsigned char NumFixItHints; - /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum /// values, with one for each argument. This specifies whether the argument /// is in DiagArgumentsStr or in DiagArguments. unsigned char DiagArgumentsKind[MaxArguments]; - - /// DiagArgumentsVal - The values for the various substitution positions. - /// This is used when the argument is not an std::string. The specific value + + /// DiagArgumentsVal - The values for the various substitution positions. + /// This is used when the argument is not an std::string. The specific value /// is mangled into an intptr_t and the interpretation depends on exactly /// what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; - + /// \brief The values for the various substitution positions that have /// string arguments. std::string DiagArgumentsStr[MaxArguments]; - + /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. CharSourceRange DiagRanges[10]; - - enum { MaxFixItHints = DiagnosticsEngine::MaxFixItHints }; - + /// FixItHints - If valid, provides a hint with some code /// to insert, remove, or modify at a particular position. - FixItHint FixItHints[MaxFixItHints]; + SmallVector<FixItHint, 6> FixItHints; }; - /// \brief An allocator for Storage objects, which uses a small cache to + /// \brief An allocator for Storage objects, which uses a small cache to /// objects, used to reduce malloc()/free() traffic for partial diagnostics. class StorageAllocator { static const unsigned NumCached = 16; Storage Cached[NumCached]; Storage *FreeList[NumCached]; unsigned NumFreeListEntries; - + public: StorageAllocator(); ~StorageAllocator(); - + /// \brief Allocate new storage. Storage *Allocate() { if (NumFreeListEntries == 0) return new Storage; - + Storage *Result = FreeList[--NumFreeListEntries]; Result->NumDiagArgs = 0; Result->NumDiagRanges = 0; - Result->NumFixItHints = 0; + Result->FixItHints.clear(); return Result; } - + /// \brief Free the given storage object. void Deallocate(Storage *S) { if (S >= Cached && S <= Cached + NumCached) { FreeList[NumFreeListEntries++] = S; return; } - + delete S; } }; - + private: // NOTE: Sema assumes that PartialDiagnostic is location-invariant // in the sense that its bits can be safely memcpy'ed and destructed @@ -114,18 +116,18 @@ private: /// DiagID - The diagnostic ID. mutable unsigned DiagID; - + /// DiagStorage - Storage for args and ranges. mutable Storage *DiagStorage; /// \brief Allocator used to allocate storage for this diagnostic. StorageAllocator *Allocator; - + /// \brief Retrieve storage for this particular diagnostic. Storage *getStorage() const { if (DiagStorage) return DiagStorage; - + if (Allocator) DiagStorage = Allocator->Allocate(); else { @@ -134,48 +136,53 @@ private: } return DiagStorage; } - - void freeStorage() { + + void freeStorage() { if (!DiagStorage) return; - + + // The hot path for PartialDiagnostic is when we just used it to wrap an ID + // (typically so we have the flexibility of passing a more complex + // diagnostic into the callee, but that does not commonly occur). + // + // Split this out into a slow function for silly compilers (*cough*) which + // can't do decent partial inlining. + freeStorageSlow(); + } + + void freeStorageSlow() { if (Allocator) Allocator->Deallocate(DiagStorage); else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) delete DiagStorage; DiagStorage = 0; } - + void AddSourceRange(const CharSourceRange &R) const { if (!DiagStorage) DiagStorage = getStorage(); - assert(DiagStorage->NumDiagRanges < + assert(DiagStorage->NumDiagRanges < llvm::array_lengthof(DiagStorage->DiagRanges) && "Too many arguments to diagnostic!"); DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R; - } + } void AddFixItHint(const FixItHint &Hint) const { if (Hint.isNull()) return; - + if (!DiagStorage) DiagStorage = getStorage(); - assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints && - "Too many code modification hints!"); - if (DiagStorage->NumFixItHints >= Storage::MaxFixItHints) - return; // Don't crash in release builds - DiagStorage->FixItHints[DiagStorage->NumFixItHints++] - = Hint; + DiagStorage->FixItHints.push_back(Hint); } - + public: PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } - - PartialDiagnostic(const PartialDiagnostic &Other) + + PartialDiagnostic(const PartialDiagnostic &Other) : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator) { if (Other.DiagStorage) { @@ -184,14 +191,14 @@ public: } } - PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) - : DiagID(Other.DiagID), DiagStorage(DiagStorage), + PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) + : DiagID(Other.DiagID), DiagStorage(DiagStorage), Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) { if (Other.DiagStorage) *this->DiagStorage = *Other.DiagStorage; } - + PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator) : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator) { @@ -202,22 +209,22 @@ public: else AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I)); } - + // Copy source ranges. for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I) AddSourceRange(Other.getRange(I)); - + // Copy fix-its. for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I) AddFixItHint(Other.getFixItHint(I)); } - + PartialDiagnostic &operator=(const PartialDiagnostic &Other) { DiagID = Other.DiagID; if (Other.DiagStorage) { if (!DiagStorage) DiagStorage = getStorage(); - + *DiagStorage = *Other.DiagStorage; } else { freeStorage(); @@ -245,7 +252,7 @@ public: void AddString(StringRef V) const { if (!DiagStorage) DiagStorage = getStorage(); - + assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && "Too many arguments to diagnostic!"); DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] @@ -256,7 +263,7 @@ public: void Emit(const DiagnosticBuilder &DB) const { if (!DiagStorage) return; - + // Add all arguments. for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { if ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i] @@ -266,25 +273,25 @@ public: DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); } - + // Add all ranges. for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i) DB.AddSourceRange(DiagStorage->DiagRanges[i]); - + // Add all fix-its. - for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i) + for (unsigned i = 0, e = DiagStorage->FixItHints.size(); i != e; ++i) DB.AddFixItHint(DiagStorage->FixItHints[i]); } - + /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID /// and removing all of its arguments, ranges, and fix-it hints. void Reset(unsigned DiagID = 0) { this->DiagID = DiagID; freeStorage(); } - + bool hasStorage() const { return DiagStorage != 0; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, unsigned I) { PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint); @@ -306,11 +313,11 @@ public: friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, StringRef S) { - + PD.AddString(S); return PD; } - + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const SourceRange &R) { PD.AddSourceRange(CharSourceRange::getTokenRange(R)); @@ -322,13 +329,13 @@ public: PD.AddSourceRange(R); return PD; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const FixItHint &Hint) { PD.AddFixItHint(Hint); return PD; } - + }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -336,7 +343,7 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, PD.Emit(DB); return DB; } - + /// \brief A partial diagnostic along with the source location where this /// diagnostic occurs. typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h index 154148c..d5fa7e7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h @@ -16,6 +16,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/Compiler.h" #include <utility> #include <functional> #include <cassert> @@ -245,6 +246,7 @@ public: /// the last token. Return false if the end of this range specifies the last /// character in the range. bool isTokenRange() const { return IsTokenRange; } + bool isCharRange() const { return !IsTokenRange; } SourceLocation getBegin() const { return Range.getBegin(); } SourceLocation getEnd() const { return Range.getEnd(); } @@ -323,7 +325,7 @@ public: /// Prints information about this FullSourceLoc to stderr. Useful for /// debugging. - void dump() const { SourceLocation::dump(*SrcMgr); } + LLVM_ATTRIBUTE_USED void dump() const; friend inline bool operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h index 985ddd6..bcb2d56 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h @@ -102,7 +102,39 @@ namespace SrcMgr { /// NumLines - The number of lines in this ContentCache. This is only valid /// if SourceLineCache is non-null. - unsigned NumLines; + unsigned NumLines : 31; + + /// \brief Indicates whether the buffer itself was provided to override + /// the actual file contents. + /// + /// When true, the original entry may be a virtual file that does not + /// exist. + unsigned BufferOverridden : 1; + + ContentCache(const FileEntry *Ent = 0) + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), + SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + + ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), + SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + + ~ContentCache(); + + /// The copy ctor does not allow copies where source object has either + /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory + /// is not transferred, so this is a logical error. + ContentCache(const ContentCache &RHS) + : Buffer(0, false), SourceLineCache(0), BufferOverridden(false) + { + OrigEntry = RHS.OrigEntry; + ContentsEntry = RHS.ContentsEntry; + + assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 && + "Passed ContentCache object cannot own a buffer."); + + NumLines = RHS.NumLines; + } /// getBuffer - Returns the memory buffer for the associated content. /// @@ -159,31 +191,6 @@ namespace SrcMgr { return (Buffer.getInt() & DoNotFreeFlag) == 0; } - ContentCache(const FileEntry *Ent = 0) - : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), - SourceLineCache(0), NumLines(0) {} - - ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) - : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(0), NumLines(0) {} - - ~ContentCache(); - - /// The copy ctor does not allow copies where source object has either - /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory - /// is not transferred, so this is a logical error. - ContentCache(const ContentCache &RHS) - : Buffer(0, false), SourceLineCache(0) - { - OrigEntry = RHS.OrigEntry; - ContentsEntry = RHS.ContentsEntry; - - assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 && - "Passed ContentCache object cannot own a buffer."); - - NumLines = RHS.NumLines; - } - private: // Disable assignments. ContentCache &operator=(const ContentCache& RHS); @@ -293,6 +300,11 @@ namespace SrcMgr { SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid(); } + bool isFunctionMacroExpansion() const { + return getExpansionLocStart().isValid() && + getExpansionLocStart() != getExpansionLocEnd(); + } + /// create - Return a ExpansionInfo for an expansion. Start and End specify /// the expansion range (where the macro is expanded), and SpellingLoc /// specifies the spelling location (where the characters from the token @@ -431,8 +443,7 @@ public: // to determine which came first. This will also take care the case where // one of the locations points at the inclusion/expansion point of the other // in which case its FileID will come before the other. - if (LOffset == ROffset && - (LQueryFID != CommonFID || RQueryFID != CommonFID)) + if (LOffset == ROffset) return IsLQFIDBeforeRQFID; return LOffset < ROffset; @@ -472,7 +483,7 @@ public: /// the case of a macro expansion, for example, the spelling location indicates /// where the expanded token came from and the expansion location specifies /// where it was expanded. -class SourceManager : public llvm::RefCountedBase<SourceManager> { +class SourceManager : public RefCountedBase<SourceManager> { /// \brief DiagnosticsEngine object. DiagnosticsEngine &Diag; @@ -508,7 +519,7 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> { /// /// Negative FileIDs are indexes into this table. To get from ID to an index, /// use (-ID - 2). - std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; + mutable std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; /// \brief The starting offset of the next local SLocEntry. /// @@ -565,11 +576,13 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> { // Cache for the "fake" buffer used for error-recovery purposes. mutable llvm::MemoryBuffer *FakeBufferForRecovery; + mutable SrcMgr::ContentCache *FakeContentCacheForRecovery; + /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. typedef std::map<unsigned, SourceLocation> MacroArgsMap; - mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap; + mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap; // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&); @@ -607,12 +620,19 @@ public: FileID getMainFileID() const { return MainFileID; } /// createMainFileID - Create the FileID for the main source file. - FileID createMainFileID(const FileEntry *SourceFile) { + FileID createMainFileID(const FileEntry *SourceFile, + SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) { assert(MainFileID.isInvalid() && "MainFileID already set!"); - MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User); + MainFileID = createFileID(SourceFile, SourceLocation(), Kind); return MainFileID; } + /// \brief Set the file ID for the main source file. + void setMainFileID(FileID FID) { + assert(MainFileID.isInvalid() && "MainFileID already set!"); + MainFileID = FID; + } + /// \brief Set the file ID for the precompiled preamble. void setPreambleFileID(FileID Preamble) { assert(PreambleFileID.isInvalid() && "PreambleFileID already set!"); @@ -641,8 +661,9 @@ public: /// specified memory buffer. This does no caching of the buffer and takes /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once. FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, - int LoadedID = 0, unsigned LoadedOffset = 0) { - return createFileID(createMemBufferContentCache(Buffer), SourceLocation(), + int LoadedID = 0, unsigned LoadedOffset = 0, + SourceLocation IncludeLoc = SourceLocation()) { + return createFileID(createMemBufferContentCache(Buffer), IncludeLoc, SrcMgr::C_User, LoadedID, LoadedOffset); } @@ -738,13 +759,19 @@ public: if (MyInvalid || !Entry.isFile()) return 0; - return Entry.getFile().getContentCache()->OrigEntry; + const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache(); + if (!Content) + return 0; + return Content->OrigEntry; } /// Returns the FileEntry record for the provided SLocEntry. const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const { - return sloc.getFile().getContentCache()->OrigEntry; + const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); + if (!Content) + return 0; + return Content->OrigEntry; } /// getBufferData - Return a StringRef to the source buffer data for the @@ -755,7 +782,7 @@ public: StringRef getBufferData(FileID FID, bool *Invalid = 0) const; /// \brief Get the number of FileIDs (files and macros) that were created - /// during preprocessing of \arg FID, including it. + /// during preprocessing of \p FID, including it. unsigned getNumCreatedFIDsForFileID(FileID FID) const { bool Invalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); @@ -766,7 +793,7 @@ public: } /// \brief Set the number of FileIDs (files and macros) that were created - /// during preprocessing of \arg FID, including it. + /// during preprocessing of \p FID, including it. void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const { bool Invalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); @@ -807,8 +834,20 @@ public: unsigned FileOffset = Entry.getOffset(); return SourceLocation::getFileLoc(FileOffset); } + + /// \brief Return the source location corresponding to the last byte of the + /// specified file. + SourceLocation getLocForEndOfFile(FileID FID) const { + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid || !Entry.isFile()) + return SourceLocation(); + + unsigned FileOffset = Entry.getOffset(); + return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID) - 1); + } - /// \brief Returns the include location if \arg FID is a #include'd file + /// \brief Returns the include location if \p FID is a #include'd file /// otherwise it returns an invalid location. SourceLocation getIncludeLoc(FileID FID) const { bool Invalid = false; @@ -828,7 +867,7 @@ public: return getExpansionLocSlowCase(Loc); } - /// \brief Given \arg Loc, if it is a macro location return the expansion + /// \brief Given \p Loc, if it is a macro location return the expansion /// location or the spelling location, depending on if it comes from a /// macro argument or not. SourceLocation getFileLoc(SourceLocation Loc) const { @@ -868,7 +907,11 @@ public: /// offset from the start of the buffer of the location. std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset()); + bool Invalid = false; + const SrcMgr::SLocEntry &E = getSLocEntry(FID, &Invalid); + if (Invalid) + return std::make_pair(FileID(), 0); + return std::make_pair(FID, Loc.getOffset()-E.getOffset()); } /// getDecomposedExpansionLoc - Decompose the specified location into a raw @@ -877,7 +920,10 @@ public: std::pair<FileID, unsigned> getDecomposedExpansionLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - const SrcMgr::SLocEntry *E = &getSLocEntry(FID); + bool Invalid = false; + const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); + if (Invalid) + return std::make_pair(FileID(), 0); unsigned Offset = Loc.getOffset()-E->getOffset(); if (Loc.isFileID()) @@ -892,7 +938,10 @@ public: std::pair<FileID, unsigned> getDecomposedSpellingLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); - const SrcMgr::SLocEntry *E = &getSLocEntry(FID); + bool Invalid = false; + const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid); + if (Invalid) + return std::make_pair(FileID(), 0); unsigned Offset = Loc.getOffset()-E->getOffset(); if (Loc.isFileID()) @@ -914,10 +963,10 @@ public: /// expanded. bool isMacroArgExpansion(SourceLocation Loc) const; - /// \brief Returns true if \arg Loc is inside the [\arg Start, +\arg Length) + /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length) /// chunk of the source location address space. - /// If it's true and \arg RelativeOffset is non-null, it will be set to the - /// relative offset of \arg Loc inside the chunk. + /// If it's true and \p RelativeOffset is non-null, it will be set to the + /// relative offset of \p Loc inside the chunk. bool isInSLocAddrSpace(SourceLocation Loc, SourceLocation Start, unsigned Length, unsigned *RelativeOffset = 0) const { @@ -938,10 +987,10 @@ public: return false; } - /// \brief Return true if both \arg LHS and \arg RHS are in the local source - /// location address space or the loaded one. If it's true and - /// \arg RelativeOffset is non-null, it will be set to the offset of \arg RHS - /// relative to \arg LHS. + /// \brief Return true if both \p LHS and \p RHS are in the local source + /// location address space or the loaded one. If it's true and \p + /// RelativeOffset is non-null, it will be set to the offset of \p RHS + /// relative to \p LHS. bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, int *RelativeOffset) const { unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset(); @@ -1041,12 +1090,17 @@ public: return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; } - /// \brief The size of the SLocEnty that \arg FID represents. + /// \brief Returns whether \p Loc is expanded from a macro in a system header. + bool isInSystemMacro(SourceLocation loc) { + return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc)); + } + + /// \brief The size of the SLocEnty that \p FID represents. unsigned getFileIDSize(FileID FID) const; - /// \brief Given a specific FileID, returns true if \arg Loc is inside that - /// FileID chunk and sets relative offset (offset of \arg Loc from beginning - /// of FileID) to \arg relativeOffset. + /// \brief Given a specific FileID, returns true if \p Loc is inside that + /// FileID chunk and sets relative offset (offset of \p Loc from beginning + /// of FileID) to \p relativeOffset. bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset = 0) const { unsigned Offs = Loc.getOffset(); @@ -1124,12 +1178,12 @@ public: /// first inclusion. FileID translateFile(const FileEntry *SourceFile) const; - /// \brief Get the source location in \arg FID for the given line:col. - /// Returns null location if \arg FID is not a file SLocEntry. + /// \brief Get the source location in \p FID for the given line:col. + /// Returns null location if \p FID is not a file SLocEntry. SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const; - /// \brief If \arg Loc points inside a function macro argument, the returned + /// \brief If \p Loc points inside a function macro argument, the returned /// location will be the macro location in which the argument was expanded. /// If a macro argument is used multiple times, the expanded location will /// be at the first expansion of the argument. @@ -1205,14 +1259,19 @@ public: unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();} /// \brief Get a loaded SLocEntry. This is exposed for indexing. - const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid=0) const { + const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, + bool *Invalid = 0) const { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); - if (!SLocEntryLoaded[Index]) - ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2)); - return LoadedSLocEntryTable[Index]; + if (SLocEntryLoaded[Index]) + return LoadedSLocEntryTable[Index]; + return loadSLocEntry(Index, Invalid); } const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { + if (FID.ID == 0 || FID.ID == -1) { + if (Invalid) *Invalid = true; + return LocalSLocEntryTable[0]; + } return getSLocEntryByID(FID.ID); } @@ -1233,18 +1292,32 @@ public: std::pair<int, unsigned> AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize); - /// \brief Returns true if \arg Loc came from a PCH/Module. + /// \brief Returns true if \p Loc came from a PCH/Module. bool isLoadedSourceLocation(SourceLocation Loc) const { return Loc.getOffset() >= CurrentLoadedOffset; } - /// \brief Returns true if \arg Loc did not come from a PCH/Module. + /// \brief Returns true if \p Loc did not come from a PCH/Module. bool isLocalSourceLocation(SourceLocation Loc) const { return Loc.getOffset() < NextLocalOffset; } + /// \brief Returns true if \p FID came from a PCH/Module. + bool isLoadedFileID(FileID FID) const { + assert(FID.ID != -1 && "Using FileID sentinel value"); + return FID.ID < 0; + } + + /// \brief Returns true if \p FID did not come from a PCH/Module. + bool isLocalFileID(FileID FID) const { + return !isLoadedFileID(FID); + } + private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; + + const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; /// \brief Get the entry with the given unwrapped FileID. const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const { @@ -1254,8 +1327,9 @@ private: return getLocalSLocEntry(static_cast<unsigned>(ID)); } - const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const { - return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2)); + const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, + bool *Invalid = 0) const { + return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); } /// createExpansionLoc - Implements the common elements of storing an diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h index 2a95d61..9e71827 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h @@ -40,6 +40,7 @@ namespace clang { TST_char16, // C++0x char16_t TST_char32, // C++0x char32_t TST_int, + TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 TST_float, TST_double, @@ -58,7 +59,7 @@ namespace clang { TST_underlyingType, // __underlying_type for C++0x TST_auto, // C++0x auto TST_unknown_anytype, // __unknown_anytype extension - TST_atomic, // C1X _Atomic + TST_atomic, // C11 _Atomic TST_error // erroneous type }; @@ -113,7 +114,12 @@ namespace clang { /// An Objective C property is a logical field of an Objective-C /// object which is read and written via Objective C method calls. - OK_ObjCProperty + OK_ObjCProperty, + + /// An Objective C array/dictionary subscripting which reads an object + /// or writes at the subscripted array/dictionary element via + /// Objective C method calls. + OK_ObjCSubscript }; // \brief Describes the kind of template specialization that a diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td index 7b3d776..67d71e4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td @@ -77,6 +77,7 @@ def ImplicitValueInitExpr : DStmt<Expr>; def ParenListExpr : DStmt<Expr>; def VAArgExpr : DStmt<Expr>; def GenericSelectionExpr : DStmt<Expr>; +def PseudoObjectExpr : DStmt<Expr>; // Atomic expressions def AtomicExpr : DStmt<Expr>; @@ -97,6 +98,7 @@ def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>; def CXXConstCastExpr : DStmt<CXXNamedCastExpr>; def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>; def CXXTypeidExpr : DStmt<Expr>; +def UserDefinedLiteral : DStmt<CallExpr>; def CXXBoolLiteralExpr : DStmt<Expr>; def CXXNullPtrLiteralExpr : DStmt<Expr>; def CXXThisExpr : DStmt<Expr>; @@ -106,6 +108,7 @@ def CXXScalarValueInitExpr : DStmt<Expr>; def CXXNewExpr : DStmt<Expr>; def CXXDeleteExpr : DStmt<Expr>; def CXXPseudoDestructorExpr : DStmt<Expr>; +def TypeTraitExpr : DStmt<Expr>; def UnaryTypeTraitExpr : DStmt<Expr>; def BinaryTypeTraitExpr : DStmt<Expr>; def ArrayTypeTraitExpr : DStmt<Expr>; @@ -126,9 +129,13 @@ def SizeOfPackExpr : DStmt<Expr>; def SubstNonTypeTemplateParmExpr : DStmt<Expr>; def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>; def MaterializeTemporaryExpr : DStmt<Expr>; +def LambdaExpr : DStmt<Expr>; // Obj-C Expressions. def ObjCStringLiteral : DStmt<Expr>; +def ObjCNumericLiteral : DStmt<Expr>; +def ObjCArrayLiteral : DStmt<Expr>; +def ObjCDictionaryLiteral : DStmt<Expr>; def ObjCEncodeExpr : DStmt<Expr>; def ObjCMessageExpr : DStmt<Expr>; def ObjCSelectorExpr : DStmt<Expr>; @@ -137,6 +144,8 @@ def ObjCIvarRefExpr : DStmt<Expr>; def ObjCPropertyRefExpr : DStmt<Expr>; def ObjCIsaExpr : DStmt<Expr>; def ObjCIndirectCopyRestoreExpr : DStmt<Expr>; +def ObjCBoolLiteralExpr : DStmt<Expr>; +def ObjCSubscriptRefExpr : DStmt<Expr>; // Obj-C ARC Expressions. def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>; @@ -147,7 +156,6 @@ def CUDAKernelCallExpr : DStmt<CallExpr>; // Clang Extensions. def ShuffleVectorExpr : DStmt<Expr>; def BlockExpr : DStmt<Expr>; -def BlockDeclRefExpr : DStmt<Expr>; def OpaqueValueExpr : DStmt<Expr>; // Microsoft Extensions. @@ -155,6 +163,7 @@ def CXXUuidofExpr : DStmt<Expr>; def SEHTryStmt : Stmt; def SEHExceptStmt : Stmt; def SEHFinallyStmt : Stmt; +def MSDependentExistsStmt : Stmt; // OpenCL Extensions. def AsTypeExpr : DStmt<Expr>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h index 8bc60ff..7c04bf7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h @@ -56,6 +56,55 @@ namespace clang { }; } + /// NeonTypeFlags - Flags to identify the types for overloaded Neon + /// builtins. These must be kept in sync with the flags in + /// utils/TableGen/NeonEmitter.h. + class NeonTypeFlags { + enum { + EltTypeMask = 0xf, + UnsignedFlag = 0x10, + QuadFlag = 0x20 + }; + uint32_t Flags; + + public: + enum EltType { + Int8, + Int16, + Int32, + Int64, + Poly8, + Poly16, + Float16, + Float32 + }; + + NeonTypeFlags(unsigned F) : Flags(F) {} + NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) { + if (IsUnsigned) + Flags |= UnsignedFlag; + if (IsQuad) + Flags |= QuadFlag; + } + + EltType getEltType() const { return (EltType)(Flags & EltTypeMask); } + bool isPoly() const { + EltType ET = getEltType(); + return ET == Poly8 || ET == Poly16; + } + bool isUnsigned() const { return (Flags & UnsignedFlag) != 0; } + bool isQuad() const { return (Flags & QuadFlag) != 0; } + }; + + /// Hexagon builtins + namespace Hexagon { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsHexagon.def" + LastTSBuiltin + }; + } } // end namespace clang. #endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h index a87af2f..bbd376a 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h @@ -59,11 +59,12 @@ enum TargetCXXABI { /// TargetInfo - This class exposes information about the current target. /// -class TargetInfo : public llvm::RefCountedBase<TargetInfo> { +class TargetInfo : public RefCountedBase<TargetInfo> { llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default // values are specified by the TargetInfo constructor. + bool BigEndian; bool TLSSupported; bool NoAsmVariants; // True if {|} are normal characters. unsigned char PointerWidth, PointerAlign; @@ -76,6 +77,7 @@ protected: unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; + unsigned char SuitableAlign; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; const char *DescriptionString; const char *UserLabelPrefix; @@ -91,6 +93,7 @@ protected: unsigned HasAlignMac68kSupport : 1; unsigned RealTypeUsesObjCFPRet : 3; + unsigned ComplexLongDoubleUsesFP2Ret : 1; // TargetInfo Constructor. Default initializes all fields. TargetInfo(const std::string &T); @@ -211,6 +214,10 @@ public: unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } + /// getSuitableAlign - Return the alignment that is suitable for storing any + /// object with a fundamental alignment requirement. + unsigned getSuitableAlign() const { return SuitableAlign; } + /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in /// bits. unsigned getWCharWidth() const { return getTypeWidth(WCharType); } @@ -249,6 +256,9 @@ public: return *LongDoubleFormat; } + /// getFloatEvalMethod - Return the value for the C99 FLT_EVAL_METHOD macro. + virtual unsigned getFloatEvalMethod() const { return 0; } + // getLargeArrayMinWidth/Align - Return the minimum array size that is // 'large' and its alignment. unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; } @@ -327,6 +337,12 @@ public: return RealTypeUsesObjCFPRet & (1 << T); } + /// \brief Check whether _Complex long double should use the "fp2ret" flavor + /// of Obj-C message passing on this target. + bool useObjCFP2RetForComplexLongDouble() const { + return ComplexLongDoubleUsesFP2Ret; + } + ///===---- Other target property query methods --------------------------===// /// getTargetDefines - Appends the target-specific #define values for this @@ -341,6 +357,13 @@ public: virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const = 0; + /// isCLZForZeroUndef - The __builtin_clz* and __builtin_ctz* built-in + /// functions are specified to have undefined results for zero inputs, but + /// on targets that support these operations in a way that provides + /// well-defined results for zero without loss of performance, it is a good + /// idea to avoid optimizing based on that undef behavior. + virtual bool isCLZForZeroUndef() const { return true; } + /// getVAListDeclaration - Return the declaration to use for /// __builtin_va_list, which is target-specific. virtual const char *getVAListDeclaration() const = 0; @@ -456,6 +479,19 @@ public: const unsigned RegNum; }; + /// hasProtectedVisibility - Does this target support "protected" + /// visibility? + /// + /// Any target which dynamic libraries will naturally support + /// something like "default" (meaning that the symbol is visible + /// outside this shared object) and "hidden" (meaning that it isn't) + /// visibilities, but "protected" is really an ELF-specific concept + /// with wierd semantics designed around the convenience of dynamic + /// linker implementations. Which is not to suggest that there's + /// consistent target-independent semantics for "default" visibility + /// either; the entire thing is pretty badly mangled. + virtual bool hasProtectedVisibility() const { return true; } + virtual bool useGlobalsForAutomaticVariables() const { return false; } /// getCFStringSection - Return the section to use for CFString @@ -551,7 +587,7 @@ public: /// /// \return - False on error (invalid feature name). virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - const std::string &Name, + StringRef Name, bool Enabled) const { return false; } @@ -565,6 +601,11 @@ public: virtual void HandleTargetFeatures(std::vector<std::string> &Features) { } + /// \brief Determine whether the given target has the given feature. + virtual bool hasFeature(StringRef Feature) const { + return false; + } + // getRegParmMax - Returns maximal number of args passed in registers. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); @@ -609,6 +650,8 @@ public: /// which the program should be compiled. VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } + bool isBigEndian() const { return BigEndian; } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def index 35a881c..2e4d34d 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def @@ -90,7 +90,8 @@ PPKEYWORD(assert) PPKEYWORD(unassert) // Clang extensions -PPKEYWORD(__export_macro__) +PPKEYWORD(__public_macro) +PPKEYWORD(__private_macro) //===----------------------------------------------------------------------===// // Language keywords. @@ -203,7 +204,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // is a keyword in the implementation namespace that should // always be treated as a keyword // KEYC99 - This is a keyword introduced to C in C99 -// KEYC1X - This is a keyword introduced to C in C1X +// KEYC11 - This is a keyword introduced to C in C11 // KEYCXX - This is a C++ keyword, or a C++-specific keyword in the // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. @@ -257,6 +258,9 @@ KEYWORD(_Generic , KEYALL) KEYWORD(_Imaginary , KEYALL) KEYWORD(_Static_assert , KEYALL) KEYWORD(__func__ , KEYALL) +KEYWORD(__objc_yes , KEYALL) +KEYWORD(__objc_no , KEYALL) + // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) @@ -328,6 +332,7 @@ KEYWORD(__builtin_types_compatible_p, KEYALL) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) KEYWORD(__imag , KEYALL) +KEYWORD(__int128 , KEYALL) KEYWORD(__label__ , KEYALL) KEYWORD(__real , KEYALL) KEYWORD(__thread , KEYALL) @@ -352,6 +357,7 @@ KEYWORD(__is_class , KEYCXX) KEYWORD(__is_convertible_to , KEYCXX) KEYWORD(__is_empty , KEYCXX) KEYWORD(__is_enum , KEYCXX) +KEYWORD(__is_final , KEYCXX) // Tentative name - there's no implementation of std::is_literal_type yet. KEYWORD(__is_literal , KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using @@ -363,7 +369,9 @@ KEYWORD(__is_trivial , KEYCXX) KEYWORD(__is_union , KEYCXX) // Clang-only C++ Type Traits +KEYWORD(__is_trivially_constructible, KEYCXX) KEYWORD(__is_trivially_copyable , KEYCXX) +KEYWORD(__is_trivially_assignable , KEYCXX) KEYWORD(__underlying_type , KEYCXX) // Embarcadero Expression Traits @@ -403,7 +411,6 @@ KEYWORD(__array_extent , KEYCXX) // Apple Extension. KEYWORD(__private_extern__ , KEYALL) -KEYWORD(__import_module__ , KEYALL) KEYWORD(__module_private__ , KEYALL) // Microsoft Extension. @@ -484,7 +491,6 @@ KEYWORD(__ptr32 , KEYMS) KEYWORD(__w64 , KEYMS) KEYWORD(__uuidof , KEYMS | KEYBORLAND) KEYWORD(__try , KEYMS | KEYBORLAND) -KEYWORD(__except , KEYMS | KEYBORLAND) KEYWORD(__finally , KEYMS | KEYBORLAND) KEYWORD(__leave , KEYMS | KEYBORLAND) KEYWORD(__int64 , KEYMS) @@ -501,7 +507,7 @@ ALIAS("_thiscall" , __thiscall , KEYMS) ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) ALIAS("_declspec" , __declspec , KEYMS) -ALIAS("__interface" , class , KEYMS) +ALIAS("__interface" , struct , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -547,6 +553,7 @@ OBJC2_AT_KEYWORD(required) OBJC2_AT_KEYWORD(optional) OBJC2_AT_KEYWORD(synthesize) OBJC2_AT_KEYWORD(dynamic) +OBJC2_AT_KEYWORD(__experimental_modules_import) // TODO: What to do about context-sensitive keywords like: // bycopy/byref/in/inout/oneway/out? @@ -559,12 +566,24 @@ ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap<int>" ANNOTATION(primary_expr) // annotation for a primary expression +ANNOTATION(decltype) // annotation for a decltype expression, + // e.g., "decltype(foo.bar())" // Annotation for #pragma unused(...) // For each argument inside the parentheses the pragma handler will produce // one 'pragma_unused' annotation token followed by the argument token. ANNOTATION(pragma_unused) +// Annotation for #pragma GCC visibility... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_vis) + +// Annotation for #pragma pack... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_pack) + #undef ANNOTATION #undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h index a7a45bd..721f44f 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h @@ -35,6 +35,7 @@ namespace clang { UTT_IsConst, UTT_IsEmpty, UTT_IsEnum, + UTT_IsFinal, UTT_IsFloatingPoint, UTT_IsFunction, UTT_IsFundamental, @@ -67,7 +68,8 @@ namespace clang { BTT_IsConvertible, BTT_IsConvertibleTo, BTT_IsSame, - BTT_TypeCompatible + BTT_TypeCompatible, + BTT_IsTriviallyAssignable }; /// ArrayTypeTrait - Names for the array type traits. @@ -82,6 +84,12 @@ namespace clang { UETT_AlignOf, UETT_VecStep }; + + /// \brief Names for type traits that operate specifically on types. + enum TypeTrait { + TT_IsTriviallyConstructible + }; + } #endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h index 15cdf1f..f3f5b5a 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Version.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header defines version macros and version-related utility functions +// This header defines version macros and version-related utility functions // for Clang. // //===----------------------------------------------------------------------===// @@ -29,7 +29,8 @@ /// \brief A string that describes the Clang version number, e.g., /// "1.0". #define CLANG_VERSION_STRING \ - CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR,CLANG_VERSION_PATCHLEVEL) + CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR, \ + CLANG_VERSION_PATCHLEVEL) #else /// \brief Helper macro for CLANG_VERSION_STRING. #define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y) @@ -41,21 +42,30 @@ #endif namespace clang { - /// \brief Retrieves the repository path (e.g., Subversion path) that + /// \brief Retrieves the repository path (e.g., Subversion path) that /// identifies the particular Clang branch, tag, or trunk from which this /// Clang was built. std::string getClangRepositoryPath(); - + + /// \brief Retrieves the repository path from which LLVM was built. Supports + /// LLVM residing in a separate repository from clang. + std::string getLLVMRepositoryPath(); + /// \brief Retrieves the repository revision number (or identifer) from which /// this Clang was built. std::string getClangRevision(); - + + /// \brief Retrieves the repository revision number (or identifer) from which + /// LLVM was built. If Clang and LLVM are in the same repository, this returns + /// the same string as getClangRevision. + std::string getLLVMRevision(); + /// \brief Retrieves the full repository version that is an amalgamation of /// the information in getClangRepositoryPath() and getClangRevision(). std::string getClangFullRepositoryVersion(); - + /// \brief Retrieves a string representing the complete clang version, - /// which includes the clang version number, the repository version, + /// which includes the clang version number, the repository version, /// and the vendor tag. std::string getClangFullVersion(); diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h index f1a2f6e..7fa589f 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h @@ -24,7 +24,8 @@ class BackendConsumer; class CodeGenAction : public ASTFrontendAction { private: unsigned Act; - llvm::OwningPtr<llvm::Module> TheModule; + OwningPtr<llvm::Module> TheModule; + llvm::Module *LinkModule; llvm::LLVMContext *VMContext; bool OwnsVMContext; @@ -46,6 +47,11 @@ protected: public: ~CodeGenAction(); + /// setLinkModule - Set the link module to be used by this action. If a link + /// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty, + /// the action will load it from the specified file. + void setLinkModule(llvm::Module *Mod) { LinkModule = Mod; } + /// takeModule - Take the generated LLVM module, for use after the action has /// been run. The result may be null on failure. llvm::Module *takeModule(); @@ -57,31 +63,37 @@ public: }; class EmitAssemblyAction : public CodeGenAction { + virtual void anchor(); public: EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0); }; class EmitBCAction : public CodeGenAction { + virtual void anchor(); public: EmitBCAction(llvm::LLVMContext *_VMContext = 0); }; class EmitLLVMAction : public CodeGenAction { + virtual void anchor(); public: EmitLLVMAction(llvm::LLVMContext *_VMContext = 0); }; class EmitLLVMOnlyAction : public CodeGenAction { + virtual void anchor(); public: EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0); }; class EmitCodeGenOnlyAction : public CodeGenAction { + virtual void anchor(); public: EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0); }; class EmitObjAction : public CodeGenAction { + virtual void anchor(); public: EmitObjAction(llvm::LLVMContext *_VMContext = 0); }; diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h index 38aba89..ba9d1f9 100644 --- a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h @@ -28,6 +28,7 @@ namespace clang { class CodeGenOptions; class CodeGenerator : public ASTConsumer { + virtual void anchor(); public: virtual llvm::Module* GetModule() = 0; virtual llvm::Module* ReleaseModule() = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h index a33c33b..6e317a0 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Action.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h @@ -39,6 +39,7 @@ public: PreprocessJobClass, PrecompileJobClass, AnalyzeJobClass, + MigrateJobClass, CompileJobClass, AssembleJobClass, LinkJobClass, @@ -94,6 +95,7 @@ public: }; class InputAction : public Action { + virtual void anchor(); const Arg &Input; public: InputAction(const Arg &_Input, types::ID _Type); @@ -107,6 +109,7 @@ public: }; class BindArchAction : public Action { + virtual void anchor(); /// The architecture to bind, or 0 if the default architecture /// should be bound. const char *ArchName; @@ -123,6 +126,7 @@ public: }; class JobAction : public Action { + virtual void anchor(); protected: JobAction(ActionClass Kind, Action *Input, types::ID Type); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); @@ -136,6 +140,7 @@ public: }; class PreprocessJobAction : public JobAction { + virtual void anchor(); public: PreprocessJobAction(Action *Input, types::ID OutputType); @@ -146,6 +151,7 @@ public: }; class PrecompileJobAction : public JobAction { + virtual void anchor(); public: PrecompileJobAction(Action *Input, types::ID OutputType); @@ -156,6 +162,7 @@ public: }; class AnalyzeJobAction : public JobAction { + virtual void anchor(); public: AnalyzeJobAction(Action *Input, types::ID OutputType); @@ -165,7 +172,19 @@ public: static bool classof(const AnalyzeJobAction *) { return true; } }; +class MigrateJobAction : public JobAction { + virtual void anchor(); +public: + MigrateJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == MigrateJobClass; + } + static bool classof(const MigrateJobAction *) { return true; } +}; + class CompileJobAction : public JobAction { + virtual void anchor(); public: CompileJobAction(Action *Input, types::ID OutputType); @@ -176,6 +195,7 @@ public: }; class AssembleJobAction : public JobAction { + virtual void anchor(); public: AssembleJobAction(Action *Input, types::ID OutputType); @@ -186,6 +206,7 @@ public: }; class LinkJobAction : public JobAction { + virtual void anchor(); public: LinkJobAction(ActionList &Inputs, types::ID Type); @@ -196,6 +217,7 @@ public: }; class LipoJobAction : public JobAction { + virtual void anchor(); public: LipoJobAction(ActionList &Inputs, types::ID Type); @@ -206,6 +228,7 @@ public: }; class DsymutilJobAction : public JobAction { + virtual void anchor(); public: DsymutilJobAction(ActionList &Inputs, types::ID Type); @@ -216,6 +239,7 @@ public: }; class VerifyJobAction : public JobAction { + virtual void anchor(); public: VerifyJobAction(ActionList &Inputs, types::ID Type); static bool classof(const Action *A) { diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h index 04faf64..3affb00 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h @@ -185,6 +185,8 @@ namespace driver { Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, OptSpecifier Id3) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4) const; /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; @@ -203,9 +205,17 @@ namespace driver { StringRef Default = "") const; /// getLastArgValue - Return the value of the last argument as an integer, + /// or a default. If Diags is non-null, emits an error if the argument + /// is given, but non-integral. + int getLastArgIntValue(OptSpecifier Id, int Default, + DiagnosticsEngine *Diags = 0) const; + + /// getLastArgValue - Return the value of the last argument as an integer, /// or a default. Emits an error if the argument is given, but non-integral. int getLastArgIntValue(OptSpecifier Id, int Default, - DiagnosticsEngine &Diags) const; + DiagnosticsEngine &Diags) const { + return getLastArgIntValue(Id, Default, &Diags); + } /// getAllArgValues - Get the values of all instances of the given argument /// as strings. diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td index b1067b7..37ba602 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td @@ -20,6 +20,10 @@ include "OptParser.td" def triple : Separate<"-triple">, HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; +def target_cpu : Separate<"-target-cpu">, + HelpText<"Target a specific cpu type">; +def target_feature : Separate<"-target-feature">, + HelpText<"Target specific attributes">; //===----------------------------------------------------------------------===// // Language Options @@ -80,3 +84,8 @@ def no_exec_stack : Flag<"--noexecstack">, def fatal_warnings : Flag<"--fatal-warnings">, HelpText<"Consider warnings as errors">; + +def g : Flag<"-g">, HelpText<"Generate source level debug information">; + +def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, + HelpText<"The string to embed in the Dwarf debug flags record.">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td index 1a12e98..88009ed 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -80,12 +80,34 @@ def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, HelpText<"Display exploded graph using GraphViz">; def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, HelpText<"Display exploded graph using Ubigraph">; -def analyzer_inline_call : Flag<"-analyzer-inline-call">, - HelpText<"Experimental transfer function inlining callees when its definition is available.">; + +def analyzer_inline_max_stack_depth : Separate<"-analyzer-inline-max-stack-depth">, + HelpText<"Bound on stack depth while inlining (4 by default)">; +def analyzer_inline_max_stack_depth_EQ : Joined<"-analyzer-inline-max-stack-depth=">, + Alias<analyzer_inline_max_stack_depth>; + +def analyzer_inline_max_function_size : Separate<"-analyzer-inline-max-function-size">, + HelpText<"Bound on the number of basic blocks in an inlined function (200 by default)">; +def analyzer_inline_max_function_size_EQ : Joined<"-analyzer-inline-max-function-size=">, + Alias<analyzer_inline_max_function_size>; + +def analyzer_ipa : Separate<"-analyzer-ipa">, + HelpText<"Specify the inter-procedural analysis mode">; +def analyzer_ipa_EQ : Joined<"-analyzer-ipa=">, Alias<analyzer_ipa>; + +def analyzer_inlining_mode : Separate<"-analyzer-inlining-mode">, + HelpText<"Specify the function selection heuristic used during inlining">; +def analyzer_inlining_mode_EQ : Joined<"-analyzer-inlining-mode=">, Alias<analyzer_inlining_mode>; + +def analyzer_disable_retry_exhausted : Flag<"-analyzer-disable-retry-exhausted">, + HelpText<"Do not re-analyze paths leading to exhausted nodes with a different strategy (may decrease code coverage)">; + def analyzer_max_nodes : Separate<"-analyzer-max-nodes">, HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">; def analyzer_max_loop : Separate<"-analyzer-max-loop">, HelpText<"The maximum number of times the analyzer will go through a loop">; +def analyzer_stats : Flag<"-analyzer-stats">, + HelpText<"Print internal analyzer statistics.">; def analyzer_checker : Separate<"-analyzer-checker">, HelpText<"Choose analyzer checkers to enable">; @@ -101,6 +123,15 @@ def analyzer_checker_help : Flag<"-analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; //===----------------------------------------------------------------------===// +// Migrator Options +//===----------------------------------------------------------------------===// +def migrator_no_nsalloc_error : Flag<"-no-ns-alloc-error">, + HelpText<"Do not error on use of NSAllocateCollectable/NSReallocateCollectable">; + +def migrator_no_finalize_removal : Flag<"-no-finalize-removal">, + HelpText<"Do not remove finalize method in gc mode">; + +//===----------------------------------------------------------------------===// // CodeGen Options //===----------------------------------------------------------------------===// @@ -110,13 +141,21 @@ def disable_llvm_verifier : Flag<"-disable-llvm-verifier">, HelpText<"Don't run the LLVM IR verifier pass">; def disable_red_zone : Flag<"-disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; +def fdebug_compilation_dir : Separate<"-fdebug-compilation-dir">, + HelpText<"The compilation directory to embed in the debug info.">; def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; +def faddress_sanitizer: Flag<"-faddress-sanitizer">, + HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">; +def fthread_sanitizer: Flag<"-fthread-sanitizer">, + HelpText<"Enable ThreadSanitizer instrumentation (race detection)">; def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def g : Flag<"-g">, HelpText<"Generate source level debug information">; def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, HelpText<"Don't use the cfi directives">; +def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, + HelpText<"Don't separate directory and filename in .file directives">; def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, HelpText<"Generate runtime checks for undefined behavior.">; def flimit_debug_info : Flag<"-flimit-debug-info">, @@ -127,6 +166,8 @@ def no_implicit_float : Flag<"-no-implicit-float">, HelpText<"Don't generate implicit floating point instructions (x86-only)">; def finstrument_functions : Flag<"-finstrument-functions">, HelpText<"Generate calls to instrument function entry and exit">; +def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, + HelpText<"Do not limit debug information produced to reduce size of debug binary">; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, HelpText<"Disallow merging of constants.">; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, @@ -137,6 +178,11 @@ def ffunction_sections : Flag<"-ffunction-sections">, HelpText<"Place each function in its own section (ELF Only)">; def fdata_sections : Flag<"-fdata-sections">, HelpText<"Place each data in its own section (ELF Only)">; +def fstrict_enums : Flag<"-fstrict-enums">, + HelpText<"Enable optimizations based on the strict definition of an enum's " + "value range.">; +def ftrap_function_EQ : Joined<"-ftrap-function=">, + HelpText<"Issue call to specified function rather than a trap instruction">; def funroll_loops : Flag<"-funroll-loops">, HelpText<"Turn on loop unroller">; def femit_coverage_notes : Flag<"-femit-coverage-notes">, @@ -158,6 +204,15 @@ def mdebug_pass : Separate<"-mdebug-pass">, HelpText<"Enable additional debug output">; def mdisable_fp_elim : Flag<"-mdisable-fp-elim">, HelpText<"Disable frame pointer elimination optimization">; +def mdisable_tail_calls : Flag<"-mdisable-tail-calls">, + HelpText<"Disable tail call optimization, keeping the call stack accurate">; +def menable_no_infinities : Flag<"-menable-no-infs">, + HelpText<"Allow optimization to assume there are no infinities.">; +def menable_no_nans : Flag<"-menable-no-nans">, + HelpText<"Allow optimization to assume there are no NaNs.">; +def menable_unsafe_fp_math : Flag<"-menable-unsafe-fp-math">, + HelpText<"Allow unsafe floating-point math optimizations which may decrease " + "precision">; def mfloat_abi : Separate<"-mfloat-abi">, HelpText<"The float ABI to use">; def mno_global_merge : Flag<"-mno-global-merge">, @@ -192,6 +247,10 @@ def mms_bitfields : Flag<"-mms-bitfields">, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; def mstackrealign : Flag<"-mstackrealign">, HelpText<"Force realign the stack at entry to every function.">; +def mstack_alignment : Joined<"-mstack-alignment=">, + HelpText<"Set the stack alignment">; +def mlink_bitcode_file : Separate<"-mlink-bitcode-file">, + HelpText<"Link the given bitcode file before performing optimizations.">; def O : Joined<"-O">, HelpText<"Optimization level">; def Os : Flag<"-Os">, HelpText<"Optimize for size">; def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">; @@ -203,6 +262,8 @@ def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">; def dependency_file : Separate<"-dependency-file">, HelpText<"Filename (or -) to write dependency output to">; +def dependency_dot : Separate<"-dependency-dot">, + HelpText<"Filename to write DOT-formatted header dependencies to">; def sys_header_deps : Flag<"-sys-header-deps">, HelpText<"Include system headers in dependency output">; def header_include_file : Separate<"-header-include-file">, @@ -224,6 +285,9 @@ def dump_build_information : Separate<"-dump-build-information">, HelpText<"output a dump of some build information to a file">; def diagnostic_log_file : Separate<"-diagnostic-log-file">, HelpText<"Filename (or -) to log diagnostics to">; +def diagnostic_serialized_file : Separate<"-serialize-diagnostic-file">, + MetaVarName<"<filename>">, + HelpText<"File for serializing diagnostics in a binary format">; def fno_show_column : Flag<"-fno-show-column">, HelpText<"Do not include column number on diagnostics">; def fshow_column : Flag<"-fshow-column">, @@ -253,8 +317,6 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang HelpText<"Print source range spans in numeric form">; def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, HelpText<"Print fix-its in machine parseable form">; -def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, - HelpText<"Print diagnostic name">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_format : Separate<"-fdiagnostics-format">, @@ -272,6 +334,8 @@ def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"< HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit).">; def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">, HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">; +def fconstexpr_backtrace_limit : Separate<"-fconstexpr-backtrace-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">; def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, @@ -364,8 +428,11 @@ def ast_view : Flag<"-ast-view">, HelpText<"Build ASTs and view them with GraphViz">; def print_decl_contexts : Flag<"-print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; +def pubnames_dump : Flag<"-pubnames-dump">, + HelpText<"Print all of the public (global) names in the source, e.g., the " + "names of all global declarations and macros">; def emit_module : Flag<"-emit-module">, - HelpText<"Generate pre-compiled module file">; + HelpText<"Generate pre-compiled module file from a module map">; def emit_pth : Flag<"-emit-pth">, HelpText<"Generate pre-tokenized header file">; def emit_pch : Flag<"-emit-pch">, @@ -388,21 +455,28 @@ def rewrite_objc : Flag<"-rewrite-objc">, HelpText<"Rewrite ObjC into C (code rewriter example)">; def rewrite_macros : Flag<"-rewrite-macros">, HelpText<"Expand macros without full preprocessing">; +def migrate : Flag<"-migrate">, + HelpText<"Migrate source code">; } +def mt_migrate_directory : Separate<"-mt-migrate-directory">, + HelpText<"Directory for temporary files produced during ARC or ObjC migration">; def arcmt_check : Flag<"-arcmt-check">, HelpText<"Check for ARC migration issues that need manual handling">; def arcmt_modify : Flag<"-arcmt-modify">, HelpText<"Apply modifications to files to conform to ARC">; def arcmt_migrate : Flag<"-arcmt-migrate">, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def arcmt_migrate_directory : Separate<"-arcmt-migrate-directory">, - HelpText<"Directory for temporary files produced during ARC migration">; def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">, HelpText<"Output path for the plist report">; def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">; +def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, + HelpText<"Enable migration to modern ObjC literals">; +def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, + HelpText<"Enable migration to modern ObjC subscripting">; + def working_directory : JoinedOrSeparate<"-working-directory">, HelpText<"Resolve file paths relative to the specified directory">; def working_directory_EQ : Joined<"-working-directory=">, @@ -416,14 +490,25 @@ def ftime_report : Flag<"-ftime-report">, HelpText<"Print the amount of time each phase of compilation takes">; def fdump_record_layouts : Flag<"-fdump-record-layouts">, HelpText<"Dump record layout information">; +def fdump_record_layouts_simple : Flag<"-fdump-record-layouts-simple">, + HelpText<"Dump record layout information in a simple form used for testing">; def fix_what_you_can : Flag<"-fix-what-you-can">, HelpText<"Apply fix-it advice even in the presence of unfixable errors">; +def fix_only_warnings : Flag<"-fix-only-warnings">, + HelpText<"Apply fix-it advice only for warnings, not errors">; +def fixit_recompile : Flag<"-fixit-recompile">, + HelpText<"Apply fix-it changes and recompile">; +def fixit_to_temp : Flag<"-fixit-to-temporary">, + HelpText<"Apply fix-it changes to temporary files">; // Generic forwarding to LLVM options. This should only be used for debugging // and experimental features. def mllvm : Separate<"-mllvm">, HelpText<"Additional arguments to forward to LLVM's option processing">; +def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">, + HelpText<"Override record layouts with those in the given file">; + //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// @@ -440,6 +525,10 @@ def fgnu_keywords : Flag<"-fgnu-keywords">, HelpText<"Allow GNU-extension keywords regardless of language standard">; def fgnu89_inline : Flag<"-fgnu89-inline">, HelpText<"Use the gnu89 inline semantics">; +def fno_inline : Flag<"-fno-inline">, + HelpText<"Disable use of the inline keyword">; +def fno_inline_functions : Flag<"-fno-inline-functions">, + HelpText<"Disable automatic function inlining">; def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, HelpText<"Disallow GNU-extension keywords regardless of language standard">; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, @@ -461,6 +550,10 @@ def fcxx_exceptions : Flag<"-fcxx-exceptions">, HelpText<"Enable C++ exceptions">; def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; +def ffast_math : Flag<"-ffast-math">, + HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " + "optimizations, but provides a preprocessor macro __FAST_MATH__ the " + "same as GCC's -ffast-math flag.">; def ffreestanding : Flag<"-ffreestanding">, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fformat_extensions : Flag<"-fformat-extensions">, @@ -541,6 +634,8 @@ def fwrapv : Flag<"-fwrapv">, HelpText<"Treat signed integer overflow as two's complement">; def pic_level : Separate<"-pic-level">, HelpText<"Value for __PIC__">; +def pie_level : Separate<"-pie-level">, + HelpText<"Value for __PIE__">; def pthread : Flag<"-pthread">, HelpText<"Support POSIX threads in generated code">; def fpack_struct : Separate<"-fpack-struct">, @@ -555,6 +650,8 @@ def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">, HelpText<"Dump declarations that are deserialized from PCH, for testing">; def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">, HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">; +def error_on_deserialized_pch_decl_EQ : Joined<"-error-on-deserialized-decl=">, + Alias<error_on_deserialized_pch_decl>; def fshort_wchar : Flag<"-fshort-wchar">, HelpText<"Force wchar_t to be a short unsigned int">; def fshort_enums : Flag<"-fshort-enums">, @@ -569,6 +666,8 @@ def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, HelpText<"Give inline C++ member functions default visibility by default">; def ftemplate_depth : Separate<"-ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; +def fconstexpr_depth : Separate<"-fconstexpr-depth">, + HelpText<"Maximum depth of recursive constexpr function calls">; def Wlarge_by_value_copy : Separate<"-Wlarge-by-value-copy">, HelpText<"Warn if a function definition returns or accepts an object larger " "in bytes that a given value">; @@ -595,10 +694,16 @@ def funknown_anytype : Flag<"-funknown-anytype">, HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; def fdebugger_support : Flag<"-fdebugger-support">, HelpText<"Enable special debugger support behavior">; +def fdebugger_cast_result_to_id : Flag<"-fdebugger-cast-result-to-id">, + HelpText<"Enable casting unknown expression results to id">; +def fdebugger_objc_literal : Flag<"-fdebugger-objc-literal">, + HelpText<"Enable special debugger support for objective-C subscripting and literals">; def fdeprecated_macro : Flag<"-fdeprecated-macro">, HelpText<"Defines the __DEPRECATED macro">; def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, HelpText<"Undefines the __DEPRECATED macro">; +def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, + HelpText<"Enable Apple gcc-compatible #pragma pack handling">; //===----------------------------------------------------------------------===// // Header Search Options @@ -613,11 +718,13 @@ def nobuiltininc : Flag<"-nobuiltininc">, def fmodule_cache_path : Separate<"-fmodule-cache-path">, MetaVarName<"<directory>">, HelpText<"Specify the module cache path">; +def fmodule_name : Joined<"-fmodule-name=">, + MetaVarName<"<name>">, + HelpText<"Specify the name of the module to build">; def fdisable_module_hash : Flag<"-fdisable-module-hash">, HelpText<"Disable the module hash">; -def fauto_module_import : Flag<"-fauto-module-import">, - HelpText<"Automatically translate #include/#import into module imports " - "when possible">; +def fmodules : Flag<"-fmodules">, + HelpText<"Enable the 'modules' language feature">; def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, HelpText<"Add directory to framework include search path">; @@ -639,6 +746,8 @@ def objc_isystem : JoinedOrSeparate<"-objc-isystem">, def objcxx_isystem : JoinedOrSeparate<"-objcxx-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the ObjC++ SYSTEM include search path">; +def iframework : JoinedOrSeparate<"-iframework">, MetaVarName<"<directory>">, + HelpText<"Add directory to SYSTEM framework search path">; def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to SYSTEM include search path">; def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">, @@ -693,6 +802,8 @@ def undef : Flag<"-undef">, MetaVarName<"<macro>">, HelpText<"undef all system defines">; def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">, HelpText<"include a detailed record of preprocessing actions">; +def mqdsp6_compat : Flag<"-mqdsp6-compat">, + HelpText<"Enable hexagon-qdsp6 backward compatibility">; //===----------------------------------------------------------------------===// // Preprocessed Output Options diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h index 8c99909..fd88c3a 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h @@ -56,6 +56,10 @@ class Compilation { /// Result files which should be removed on failure. ArgStringList ResultFiles; + /// Result files which are generated correctly on failure, and which should + /// only be removed if we crash. + ArgStringList FailureResultFiles; + /// Redirection for stdout, stderr, etc. const llvm::sys::Path **Redirects; @@ -84,6 +88,10 @@ public: const ArgStringList &getResultFiles() const { return ResultFiles; } + const ArgStringList &getFailureResultFiles() const { + return FailureResultFiles; + } + /// getArgsForToolChain - Return the derived argument list for the /// tool chain \arg TC (or the default tool chain, if TC is not /// specified). @@ -106,6 +114,13 @@ public: return Name; } + /// addFailureResultFile - Add a file to remove if we crash, and returns its + /// argument. + const char *addFailureResultFile(const char *Name) { + FailureResultFiles.push_back(Name); + return Name; + } + /// CleanupFileList - Remove the files in the given list. /// /// \param IssueErrors - Report failures as errors. diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h index 6fdf6fc..0538334 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h @@ -16,6 +16,7 @@ #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo @@ -35,7 +36,6 @@ namespace driver { class Command; class Compilation; class DerivedArgList; - class HostInfo; class InputArgList; class InputInfo; class JobAction; @@ -86,8 +86,8 @@ public: /// If the standard library is used bool UseStdLib; - /// Default host triple. - std::string DefaultHostTriple; + /// Default target triple. + std::string DefaultTargetTriple; /// Default name for linked images (e.g., "a.out"). std::string DefaultImageName; @@ -95,10 +95,6 @@ public: /// 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; - /// Information about the host which can be overridden by the user. std::string HostBits, HostMachine, HostSystem, HostRelease; @@ -117,7 +113,7 @@ public: /// Whether the driver should follow g++ like behavior. unsigned CCCIsCXX : 1; - /// Whether the driver is just the preprocessor + /// Whether the driver is just the preprocessor. unsigned CCCIsCPP : 1; /// Echo commands while executing (in -v style). @@ -175,6 +171,13 @@ private: std::list<std::string> TempFiles; std::list<std::string> ResultFiles; + /// \brief Cache of all the ToolChains in use by the driver. + /// + /// This maps from the string representation of a triple to a ToolChain + /// created targetting that triple. The driver owns all the ToolChain objects + /// stored in it, and will clean them up when torn down. + mutable llvm::StringMap<ToolChain *> ToolChains; + private: /// TranslateInputArgs - Create a new derived argument list from the input /// arguments, after applying the standard argument translations. @@ -187,7 +190,7 @@ private: public: Driver(StringRef _ClangExecutable, - StringRef _DefaultHostTriple, + StringRef _DefaultTargetTriple, StringRef _DefaultImageName, bool IsProduction, DiagnosticsEngine &_Diags); @@ -379,10 +382,6 @@ public: /// GCC goes to extra lengths here to be a bit more robust. std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const; - /// GetHostInfo - Construct a new host info object for the given - /// host triple. - const HostInfo *GetHostInfo(const char *HostTriple) const; - /// ShouldUseClangCompilar - Should the clang compiler be used to /// handle this action. bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, @@ -390,8 +389,17 @@ public: bool IsUsingLTO(const ArgList &Args) const; +private: + /// \brief Retrieves a ToolChain for a particular target triple. + /// + /// Will cache ToolChains for the life of the driver object, and create them + /// on-demand. + const ToolChain &getToolChain(const ArgList &Args, + StringRef DarwinArchName = "") const; + /// @} +public: /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and /// return the grouped values as integers. Numbers which are not /// provided are set to 0. diff --git a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h index 844f918..ea7b52f 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define DRIVERSTART #include "clang/Basic/DiagnosticDriverKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h b/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h deleted file mode 100644 index 7285a48..0000000 --- a/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h +++ /dev/null @@ -1,94 +0,0 @@ -//===--- HostInfo.h - Host specific information -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_DRIVER_HOSTINFO_H_ -#define CLANG_DRIVER_HOSTINFO_H_ - -#include "llvm/ADT/Triple.h" -#include <string> - -namespace clang { -namespace driver { - class ArgList; - class Driver; - class ToolChain; - -/// HostInfo - Config information about a particular host which may interact -/// with driver behavior. -/// -/// The host information is used for controlling the parts of the driver which -/// interact with the platform the driver is ostensibly being run from. For -/// testing purposes, the HostInfo used by the driver may differ from the actual -/// host. -class HostInfo { -protected: - const Driver &TheDriver; - const llvm::Triple Triple; - - HostInfo(const Driver &D, const llvm::Triple &_Triple); - -public: - virtual ~HostInfo(); - - const Driver &getDriver() const { return TheDriver; } - - const llvm::Triple& getTriple() const { return Triple; } - std::string getArchName() const { return Triple.getArchName(); } - std::string getPlatformName() const { return Triple.getVendorName(); } - std::string getOSName() const { return Triple.getOSName(); } - - /// useDriverDriver - Whether the driver should act as a driver driver for - /// this host and support -arch, -Xarch, etc. - virtual bool useDriverDriver() const = 0; - - /// CreateToolChain - Construct the toolchain to use for this host (which the - /// host retains ownership of). - /// - /// \param Args - The argument list, which may be used to alter the default - /// toolchain, for example in the presence of -m32 or -m64. - /// - /// \param ArchName - The architecture to return a toolchain for, or 0 if - /// unspecified. This will only ever be non-zero for hosts which support a - /// driver driver. - - // FIXME: Pin down exactly what the HostInfo is allowed to use Args - // for here. Currently this is for -m32 / -m64 defaulting. - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName=0) const = 0; -}; - -const HostInfo *createAuroraUXHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createDarwinHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createOpenBSDHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createFreeBSDHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createNetBSDHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createMinixHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createDragonFlyHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createLinuxHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createTCEHostInfo(const Driver &D, - const llvm::Triple& Triple); -const HostInfo *createWindowsHostInfo(const Driver &D, - const llvm::Triple &Triple); -const HostInfo *createMinGWHostInfo(const Driver &D, - const llvm::Triple &Triple); -const HostInfo *createUnknownHostInfo(const Driver &D, - const llvm::Triple& Triple); - -} // end namespace driver -} // end namespace clang - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h index 367955f..c94886d 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Job.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h @@ -46,6 +46,8 @@ public: /// Command - An executable path/name and argument vector to /// execute. class Command : public Job { + virtual void anchor(); + /// Source - The action which caused the creation of this job. const Action &Source; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ObjCRuntime.h b/contrib/llvm/tools/clang/include/clang/Driver/ObjCRuntime.h index 5516460..094873a 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/ObjCRuntime.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/ObjCRuntime.h @@ -30,6 +30,9 @@ public: /// True if the runtime supports ARC zeroing __weak. unsigned HasWeak : 1; + /// \brief True if the runtime supports subscripting methods. + unsigned HasSubscripting : 1; + /// True if the runtime provides the following entrypoint: /// void objc_terminate(void); /// If available, this will be called instead of abort() when an @@ -37,7 +40,7 @@ public: unsigned HasTerminate : 1; ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false), - HasTerminate(false) {} + HasSubscripting(false), HasTerminate(false) {} }; } diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h index abd224d..3af6f8f 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h @@ -49,8 +49,8 @@ namespace options { const char *HelpText; const char *MetaVar; unsigned char Kind; - unsigned short Flags; unsigned char Param; + unsigned short Flags; unsigned short GroupID; unsigned short AliasID; }; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td index 5b91c19..0a29bb9 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td @@ -21,6 +21,7 @@ include "OptParser.td" def CompileOnly_Group : OptionGroup<"<CompileOnly group>">; def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>; +def L_Group : OptionGroup<"<L group>">, Group<CompileOnly_Group>; def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>; def T_Group : OptionGroup<"<T group>">; def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>; @@ -101,8 +102,6 @@ def ccc_pch_is_pth : Flag<"-ccc-pch-is-pth">, CCCDriverOpt, HelpText<"Use pretokenized headers for precompiled headers">; class CCCDebugOpt : Group<ccc_debug_Group>, Flags<[DriverOption, HelpHidden]>; -def ccc_host_triple : Separate<"-ccc-host-triple">, CCCDebugOpt, - HelpText<"Simulate running on the given target">; def ccc_install_dir : Separate<"-ccc-install-dir">, CCCDebugOpt, HelpText<"Simulate installation in the given directory">; def ccc_print_options : Flag<"-ccc-print-options">, CCCDebugOpt, @@ -120,13 +119,21 @@ def ccc_arrmt_check : Flag<"-ccc-arrmt-check">, Alias<ccc_arcmt_check>; def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias<ccc_arcmt_modify>; def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def ccc_arcmt_migrate_EQ : Joined<"-ccc-arcmt-migrate=">, CCCDriverOpt, - Alias<ccc_arcmt_migrate>; def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">, HelpText<"Output path for the plist report">; def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">; +def _migrate : Flag<"--migrate">, Flags<[DriverOption]>, + HelpText<"Run the migrator">; +def ccc_objcmt_migrate : Separate<"-ccc-objcmt-migrate">, CCCDriverOpt, + HelpText<"Apply modifications and produces temporary files to migrate to " + "modern ObjC syntax">; +def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, + HelpText<"Enable migration to modern ObjC literals">; +def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, + HelpText<"Enable migration to modern ObjC subscripting">; + // Make sure all other -ccc- options are rejected. def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>; @@ -145,6 +152,7 @@ def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; def E : Flag<"-E">, Flags<[DriverOption]>, HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined]>; +def G : Separate<"-G">, Flags<[DriverOption]>; def H : Flag<"-H">; def I_ : Flag<"-I-">, Group<I_Group>; def I : JoinedOrSeparate<"-I">, Group<I_Group>; @@ -229,7 +237,7 @@ def client__name : JoinedOrSeparate<"-client_name">; def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<"-compatibility_version">; def coverage : Flag<"-coverage">; -def cpp_precomp : Flag<"-cpp-precomp">; +def cpp_precomp : Flag<"-cpp-precomp">, Group<clang_ignored_f_Group>; def current__version : JoinedOrSeparate<"-current_version">; def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>; def c : Flag<"-c">, Flags<[DriverOption]>, @@ -256,11 +264,18 @@ def emit_llvm : Flag<"-emit-llvm">, def exported__symbols__list : Separate<"-exported_symbols_list">; def e : JoinedOrSeparate<"-e">; def fPIC : Flag<"-fPIC">, Group<f_Group>; -def fPIE : Flag<"-fPIE">, Group<f_Group>, Flags<[NoArgumentUnused]>; -def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>, Flags<[NoArgumentUnused]>; +def fno_PIC : Flag<"-fno-PIC">, Group<f_Group>; +def fPIE : Flag<"-fPIE">, Group<f_Group>; +def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>; def faccess_control : Flag<"-faccess-control">, Group<f_Group>; def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>; +def faltivec : Flag<"-faltivec">, Group<f_Group>; def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; +def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group<f_Group>; +def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group<f_Group>; +def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group<f_Group>; +def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group<f_Group>; +def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group<f_Group>; def fasm : Flag<"-fasm">, Group<f_Group>; def fasm_blocks : Flag<"-fasm-blocks">, Group<f_Group>; @@ -286,21 +301,27 @@ def fcommon : Flag<"-fcommon">, Group<f_Group>; def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>; def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>; def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Group>; +def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group<f_Group>; +def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, + Group<f_Group>; +def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>; +def fcxx_modules : Flag <"-fcxx-modules">, Group<f_Group>, Flags<[NoForward]>; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_clang_Group>; def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_clang_Group>; def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; -def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group<f_Group>; def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group<f_Group>; def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group<f_clang_Group>; def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>; def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>; +def fdwarf_directory_asm : Flag<"-fdwarf-directory-asm">, Group<f_Group>; +def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>; def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>; def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>; def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; @@ -309,8 +330,34 @@ def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; -def ffast_math : Flag<"-ffast-math">, Group<clang_ignored_f_Group>; -def ffinite_math_only : Flag<"-ffinite-math-only">, Group<clang_ignored_f_Group>; +def ffast_math : Flag<"-ffast-math">, Group<f_Group>; +def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; +def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; +def fsignaling_math : Flag<"-fsignaling-math">, Group<f_Group>; +def fno_signaling_math : Flag<"-fno-signaling-math">, Group<f_Group>; +def funsafe_math_optimizations : Flag<"-funsafe-math-optimizations">, + Group<f_Group>; +def fno_unsafe_math_optimizations : Flag<"-fno-unsafe-math-optimizations">, + Group<f_Group>; +def fassociative_math : Flag<"-fassociative-math">, Group<f_Group>; +def fno_associative_math : Flag<"-fno-associative-math">, Group<f_Group>; +def freciprocal_math : Flag<"-freciprocal-math">, Group<f_Group>; +def fno_reciprocal_math : Flag<"-fno-reciprocal-math">, Group<f_Group>; +def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>; +def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<f_Group>; +def fsigned_zeros : Flag<"-fsigned-zeros">, Group<f_Group>; +def fno_signed_zeros : Flag<"-fno-signed-zeros">, Group<f_Group>; +def fhonor_nans : Flag<"-fhonor-nans">, Group<f_Group>; +def fno_honor_nans : Flag<"-fno-honor-nans">, Group<f_Group>; +def fhonor_infinities : Flag<"-fhonor-infinities">, Group<f_Group>; +def fno_honor_infinities : Flag<"-fno-honor-infinities">, Group<f_Group>; +// Sic. This option was misspelled originally. +def fhonor_infinites : Flag<"-fhonor-infinites">, Group<f_Group>, + Alias<fhonor_infinities>; +def fno_honor_infinites : Flag<"-fno-honor-infinites">, Group<f_Group>, + Alias<fno_honor_infinities>; +def ftrapping_math : Flag<"-ftrapping-math">, Group<f_Group>; +def fno_trapping_math : Flag<"-fno-trapping-math">, Group<f_Group>; def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>; def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>; @@ -337,7 +384,6 @@ def flto : Flag<"-flto">, Group<f_Group>; def fno_lto : Flag<"-fno-lto">, Group<f_Group>; def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, Group<f_Group>; -def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>; def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>; def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>; @@ -346,14 +392,14 @@ def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>; def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>; def fmodule_cache_path : Separate<"-fmodule-cache-path">, Group<i_Group>, Flags<[NoForward]>; -def fauto_module_import : Flag <"-fauto-module-import">, Group<f_Group>, - Flags<[NoForward]>; +def fmodules : Flag <"-fmodules">, Group<f_Group>, Flags<[NoForward]>; def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>; def fmudflap : Flag<"-fmudflap">, Group<f_Group>; def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>; def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>; +def fno_apple_pragma_pack : Flag<"-fno-apple-pragma-pack">, Group<f_Group>; def fno_asm : Flag<"-fno-asm">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>; @@ -367,30 +413,30 @@ def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>; def fno_common : Flag<"-fno-common">, Group<f_Group>; def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>; def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group<f_Group>; +def fno_cxx_modules : Flag <"-fno-cxx-modules">, Group<f_Group>, Flags<[NoForward]>; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>; -def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group<f_Group>; def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>; def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, Group<f_Group>; def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; -def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<clang_ignored_f_Group>; def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; -def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; -def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; +def fno_inline_functions : Flag<"-fno-inline-functions">, Group<f_Group>; +def fno_inline : Flag<"-fno-inline">, Group<f_Group>; def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>; def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>; -def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; +def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>, + HelpText<"Do not limit debug information produced to reduce size of debug binary">; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; +def fno_modules : Flag <"-fno-modules">, Group<f_Group>, Flags<[NoForward]>; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; def fno_ms_compatibility : Flag<"-fno-ms-compatibility">, Group<f_Group>; def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group<f_Group>; -def fno_objc_default_synthesize_properties - : Flag<"-fno-objc-default-synthesize-properties">, Group<f_Group>; def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>; def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>; def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>; +def fno_operator_names : Flag<"-fno-operator-names">, Group<f_Group>; def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; def fno_short_enums : Flag<"-fno-short-enums">, Group<f_Group>; @@ -399,6 +445,7 @@ def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group> def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>; def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>; +def fno_strict_enums : Flag<"-fno-strict-enums">, Group<f_Group>; def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group<f_Group>; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>; @@ -414,8 +461,6 @@ def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>; def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group<f_Group>; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; -def fobjc_default_synthesize_properties : - Flag<"-fobjc-default-synthesize-properties">, Group<f_Group>; def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>; def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; @@ -426,6 +471,7 @@ def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, Group<f_Group>; def fno_objc_infer_related_result_type : Flag< "-fno-objc-infer-related-result-type">, Group<f_Group>; +def fobjc_link_runtime: Flag<"-fobjc-link-runtime">, Group<f_Group>; // Objective-C ABI options. def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>; @@ -437,6 +483,8 @@ def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, def fobjc : Flag<"-fobjc">, Group<f_Group>; def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>; def fopenmp : Flag<"-fopenmp">, Group<f_Group>; +def fno_optimize_sibling_calls : Flag<"-fno-optimize-sibling-calls">, Group<f_Group>; +def foptimize_sibling_calls : Flag<"-foptimize-sibling-calls">, Group<f_Group>; def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">; def force__flat__namespace : Flag<"-force_flat_namespace">; def force__load : Separate<"-force_load">; @@ -447,8 +495,9 @@ def fpack_struct_EQ : Joined<"-fpack-struct=">, Group<f_Group>; def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>; def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>; def fpic : Flag<"-fpic">, Group<f_Group>; -def fpie : Flag<"-fpie">, Group<f_Group>, Flags<[NoArgumentUnused]>; -def fno_pie : Flag<"-fno-pie">, Group<f_Group>, Flags<[NoArgumentUnused]>; +def fno_pic : Flag<"-fno-pic">, Group<f_Group>; +def fpie : Flag<"-fpie">, Group<f_Group>; +def fno_pie : Flag<"-fno-pie">, Group<f_Group>; def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>; def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>; def framework : Separate<"-framework">, Flags<[LinkerInput]>; @@ -467,9 +516,11 @@ def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>; def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>; def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>; def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>; +def fstrict_enums : Flag<"-fstrict-enums">, Group<f_Group>; def fstrict_overflow : Flag<"-fstrict-overflow">, Group<f_Group>; def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; +def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group<f_Group>; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, Group<f_Group>; @@ -506,17 +557,22 @@ def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group> def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>; def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>; def f : Joined<"-f">, Group<f_Group>; -def g0 : Joined<"-g0">, Group<g_Group>; -def g3 : Joined<"-g3">, Group<g_Group>; -def gfull : Joined<"-gfull">, Group<g_Group>; -def gstabs : Joined<"-gstabs">, Group<g_Group>; -def gused : Joined<"-gused">, Group<g_Group>; +def g0 : Flag<"-g0">, Group<g_Group>; +def g2 : Flag<"-g2">, Group<g_Group>; +def g3 : Flag<"-g3">, Group<g_Group>; +def gdwarf2 : Flag<"-gdwarf-2">, Group<g_Group>; +def gfull : Flag<"-gfull">, Group<g_Group>; +def ggdb : Flag<"-ggdb">, Group<g_Group>; +def gstabs : Flag<"-gstabs">, Group<g_Group>; +def gstabsplus : Flag<"-gstabs+">, Group<g_Group>; +def gstabs1 : Flag<"-gstabs1">, Group<g_Group>; +def gstabs2 : Flag<"-gstabs2">, Group<g_Group>; +def gused : Flag<"-gused">, Group<g_Group>; def g_Flag : Flag<"-g">, Group<g_Group>; -def g_Joined : Joined<"-g">, Group<g_Group>; def headerpad__max__install__names : Joined<"-headerpad_max_install_names">; def index_header_map : Flag<"-index-header-map">; def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>; -def iframework : JoinedOrSeparate<"-iframework">, Group<clang_i_Group>; +def iframework : Joined<"-iframework">, Group<clang_i_Group>; def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>; def image__base : Separate<"-image_base">; def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">; @@ -534,7 +590,10 @@ def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>; def i : Joined<"-i">, Group<i_Group>; def keep__private__externs : Flag<"-keep_private_externs">; def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>; +def lazy__framework : Separate<"-lazy_framework">, Flags<[LinkerInput]>; +def lazy__library : Separate<"-lazy_library">, Flags<[LinkerInput]>; def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>; +def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption]>; def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>; def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>; def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>; @@ -543,9 +602,10 @@ def march_EQ : Joined<"-march=">, Group<m_Group>; def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>; def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>; def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>; -def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>; +def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>; def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>; def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; +def mfpmath_EQ : Joined<"-mfpmath=">, Group<m_Group>; def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>; def mglobal_merge : Flag<"-mglobal-merge">, Group<m_Group>; def mhard_float : Flag<"-mhard-float">, Group<m_Group>; @@ -558,6 +618,7 @@ def mllvm : Separate<"-mllvm">; def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>; def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>; def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>; +def mstack_alignment : Joined<"-mstack-alignment=">, Group<m_Group>; def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>; def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>; def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>; @@ -569,6 +630,7 @@ def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; def mno_relax_all : Flag<"-mno-relax-all">, Group<m_Group>; def mno_rtd: Flag<"-mno-rtd">, Group<m_Group>; def mno_soft_float : Flag<"-mno-soft-float">, Group<m_Group>; +def mno_stackrealign : Flag<"-mno-stackrealign">, Group<m_Group>; def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>; def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>; def mno_sse4a : Flag<"-mno-sse4a">, Group<m_x86_Features_Group>; @@ -579,6 +641,12 @@ def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>; def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>; +def mno_avx2 : Flag<"-mno-avx2">, Group<m_x86_Features_Group>; +def mno_lzcnt : Flag<"-mno-lzcnt">, Group<m_x86_Features_Group>; +def mno_bmi : Flag<"-mno-bmi">, Group<m_x86_Features_Group>; +def mno_bmi2 : Flag<"-mno-bmi2">, Group<m_x86_Features_Group>; +def mno_popcnt : Flag<"-mno-popcnt">, Group<m_x86_Features_Group>; +def mno_fma4 : Flag<"-mno-fma4">, Group<m_x86_Features_Group>; def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; def marm : Flag<"-marm">, Alias<mno_thumb>; @@ -591,6 +659,7 @@ def mred_zone : Flag<"-mred-zone">, Group<m_Group>; def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>; def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>; def mrtd: Flag<"-mrtd">, Group<m_Group>; +def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group<m_Group>; def msoft_float : Flag<"-msoft-float">, Group<m_Group>; def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; @@ -602,6 +671,12 @@ def msse : Flag<"-msse">, Group<m_x86_Features_Group>; def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; def maes : Flag<"-maes">, Group<m_x86_Features_Group>; def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>; +def mavx2 : Flag<"-mavx2">, Group<m_x86_Features_Group>; +def mlzcnt : Flag<"-mlzcnt">, Group<m_x86_Features_Group>; +def mbmi : Flag<"-mbmi">, Group<m_x86_Features_Group>; +def mbmi2 : Flag<"-mbmi2">, Group<m_x86_Features_Group>; +def mpopcnt : Flag<"-mpopcnt">, Group<m_x86_Features_Group>; +def mfma4 : Flag<"-mfma4">, Group<m_x86_Features_Group>; def mthumb : Flag<"-mthumb">, Group<m_Group>; def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; def multi__module : Flag<"-multi_module">; @@ -612,7 +687,7 @@ 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<[HelpHidden]>, HelpText<"Use relative instead of canonical paths">; -def no_cpp_precomp : Flag<"-no-cpp-precomp">; +def no_cpp_precomp : Flag<"-no-cpp-precomp">, Group<clang_ignored_f_Group>; def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; @@ -662,8 +737,11 @@ def read__only__relocs : Separate<"-read_only_relocs">; def remap : Flag<"-remap">; def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption]>, HelpText<"Rewrite Objective-C source to C++">; +def rewrite_legacy_objc : Flag<"-rewrite-legacy-objc">, Flags<[DriverOption]>, + HelpText<"Rewrite Legacy Objective-C source to C++">; def rdynamic : Flag<"-rdynamic">; def rpath : Separate<"-rpath">, Flags<[LinkerInput]>; +def rtlib_EQ : Joined<"-rtlib=">; def r : Flag<"-r">; def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>, HelpText<"Save intermediate compilation results">; @@ -687,13 +765,20 @@ def single__module : Flag<"-single_module">; def specs_EQ : Joined<"-specs=">; def specs : Separate<"-specs">, Flags<[Unsupported]>; def static_libgcc : Flag<"-static-libgcc">; +def static_libstdcxx : Flag<"-static-libstdc++">; def static : Flag<"-static">, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<"-std-default=">; -def std_EQ : Joined<"-std=">; +def std_EQ : Joined<"-std=">, Group<L_Group>; def stdlib_EQ : Joined<"-stdlib=">; def sub__library : JoinedOrSeparate<"-sub_library">; def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">; def s : Flag<"-s">; +def target : Separate<"-target">, Flags<[DriverOption]>, + HelpText<"Generate code for the given target">; +def gcc_toolchain : Separate<"-gcc-toolchain">, Flags<[DriverOption]>, + HelpText<"Use the gcc toolchain at the given directory">; +// We should deprecate the use of -ccc-host-triple, and then remove. +def ccc_host_triple : Separate<"-ccc-host-triple">, Alias<target>; def time : Flag<"-time">, HelpText<"Time individual commands">; def traditional_cpp : Flag<"-traditional-cpp">; @@ -835,7 +920,11 @@ def _relocatable_pch : Flag<"--relocatable-pch">, HelpText<"Build a relocatable precompiled header">; def _resource_EQ : Joined<"--resource=">, Alias<fcompile_resource_EQ>; def _resource : Separate<"--resource">, Alias<fcompile_resource_EQ>; +def _rtlib_EQ : Joined<"--rtlib=">, Alias<rtlib_EQ>; +def _rtlib : Separate<"--rtlib">, Alias<rtlib_EQ>; def _save_temps : Flag<"--save-temps">, Alias<save_temps>; +def _serialize_diags : Separate<"--serialize-diagnostics">, Flags<[DriverOption]>, + HelpText<"Serialize compiler diagnostics to a file">; def _shared : Flag<"--shared">, Alias<shared>; def _signed_char : Flag<"--signed-char">, Alias<fsigned_char>; def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h index 378b516..8822d7b 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h @@ -49,6 +49,7 @@ public: virtual bool hasIntegratedAssembler() const { return false; } virtual bool hasIntegratedCPP() const = 0; + virtual bool isLinkJob() const { return false; } /// \brief Does this tool have "good" standardized diagnostics, or should the /// driver add an additional "command failed" diagnostic on failures. diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h index 2e6218a..c35cf67 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h @@ -23,7 +23,6 @@ namespace driver { class Compilation; class DerivedArgList; class Driver; - class HostInfo; class InputArgList; class JobAction; class ObjCRuntime; @@ -39,8 +38,13 @@ public: CST_Libstdcxx }; + enum RuntimeLibType { + RLT_CompilerRT, + RLT_Libgcc + }; + private: - const HostInfo &Host; + const Driver &D; const llvm::Triple Triple; /// The list of toolchain specific path prefixes to search for @@ -52,7 +56,20 @@ private: path_list ProgramPaths; protected: - ToolChain(const HostInfo &Host, const llvm::Triple &_Triple); + ToolChain(const Driver &D, const llvm::Triple &T); + + /// \name Utilities for implementing subclasses. + ///@{ + static void addSystemInclude(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const Twine &Path); + static void addExternCSystemInclude(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const Twine &Path); + static void addSystemIncludes(const ArgList &DriverArgs, + ArgStringList &CC1Args, + ArrayRef<StringRef> Paths); + ///@} public: virtual ~ToolChain(); @@ -131,7 +148,7 @@ public: /// IsObjCLegacyDispatchDefault - Does this tool chain set /// -fobjc-legacy-dispatch by default (this is only used with the non-fragile /// ABI). - virtual bool IsObjCLegacyDispatchDefault() const { return false; } + virtual bool IsObjCLegacyDispatchDefault() const { return true; } /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the /// mixed dispatch method be used? @@ -143,6 +160,11 @@ public: return 0; } + /// GetDefaultRuntimeLibType - Get the default runtime library variant to use. + virtual RuntimeLibType GetDefaultRuntimeLibType() const { + return ToolChain::RLT_Libgcc; + } + /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables /// by default. virtual bool IsUnwindTablesDefault() const = 0; @@ -162,6 +184,9 @@ public: /// Does this tool chain support Objective-C garbage collection. virtual bool SupportsObjCGC() const { return true; } + /// Does this tool chain support Objective-C ARC. + virtual bool SupportsObjCARC() const { return true; } + /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf /// compile unit information. virtual bool UseDwarfDebugFlags() const { return false; } @@ -202,6 +227,10 @@ public: virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; + // GetRuntimeLibType - Determine the runtime library type to use with the + // given compilation arguments. + virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const; + // GetCXXStdlibType - Determine the C++ standard library type to use with the // given compilation arguments. virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.def b/contrib/llvm/tools/clang/include/clang/Driver/Types.def index 8449d63..b107dfb 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Types.def +++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def @@ -82,6 +82,8 @@ TYPE("lto-bc", LTO_BC, INVALID, "o", "") TYPE("ast", AST, INVALID, "ast", "u") TYPE("plist", Plist, INVALID, "plist", "") TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "") +TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", "") +TYPE("remap", Remap, INVALID, "remap", "") TYPE("precompiled-header", PCH, INVALID, "gch", "A") TYPE("object", Object, INVALID, "o", "") TYPE("treelang", Treelang, INVALID, 0, "u") diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h new file mode 100644 index 0000000..aaf6b18 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h @@ -0,0 +1,140 @@ +//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EDIT_COMMIT_H +#define LLVM_CLANG_EDIT_COMMIT_H + +#include "clang/Edit/FileOffset.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class LangOptions; + class PreprocessingRecord; + +namespace edit { + class EditedSource; + +class Commit { +public: + enum EditKind { + Act_Insert, + Act_InsertFromRange, + Act_Remove + }; + + struct Edit { + EditKind Kind; + StringRef Text; + SourceLocation OrigLoc; + FileOffset Offset; + FileOffset InsertFromRangeOffs; + unsigned Length; + bool BeforePrev; + + SourceLocation getFileLocation(SourceManager &SM) const; + CharSourceRange getFileRange(SourceManager &SM) const; + CharSourceRange getInsertFromRange(SourceManager &SM) const; + }; + +private: + const SourceManager &SourceMgr; + const LangOptions &LangOpts; + const PreprocessingRecord *PPRec; + EditedSource *Editor; + + bool IsCommitable; + SmallVector<Edit, 8> CachedEdits; + +public: + explicit Commit(EditedSource &Editor); + Commit(const SourceManager &SM, const LangOptions &LangOpts, + const PreprocessingRecord *PPRec = 0) + : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0), + IsCommitable(true) { } + + bool isCommitable() const { return IsCommitable; } + + bool insert(SourceLocation loc, StringRef text, bool afterToken = false, + bool beforePreviousInsertions = false); + bool insertAfterToken(SourceLocation loc, StringRef text, + bool beforePreviousInsertions = false) { + return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions); + } + bool insertBefore(SourceLocation loc, StringRef text) { + return insert(loc, text, /*afterToken=*/false, + /*beforePreviousInsertions=*/true); + } + bool insertFromRange(SourceLocation loc, CharSourceRange range, + bool afterToken = false, + bool beforePreviousInsertions = false); + bool insertWrap(StringRef before, CharSourceRange range, StringRef after); + + bool remove(CharSourceRange range); + + bool replace(CharSourceRange range, StringRef text); + bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange); + bool replaceText(SourceLocation loc, StringRef text, + StringRef replacementText); + + bool insertFromRange(SourceLocation loc, SourceRange TokenRange, + bool afterToken = false, + bool beforePreviousInsertions = false) { + return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange), + afterToken, beforePreviousInsertions); + } + bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { + return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); + } + bool remove(SourceRange TokenRange) { + return remove(CharSourceRange::getTokenRange(TokenRange)); + } + bool replace(SourceRange TokenRange, StringRef text) { + return replace(CharSourceRange::getTokenRange(TokenRange), text); + } + bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) { + return replaceWithInner(CharSourceRange::getTokenRange(TokenRange), + CharSourceRange::getTokenRange(TokenInnerRange)); + } + + typedef SmallVector<Edit, 8>::const_iterator edit_iterator; + edit_iterator edit_begin() const { return CachedEdits.begin(); } + edit_iterator edit_end() const { return CachedEdits.end(); } + +private: + void addInsert(SourceLocation OrigLoc, + FileOffset Offs, StringRef text, bool beforePreviousInsertions); + void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, + FileOffset RangeOffs, unsigned RangeLen, + bool beforePreviousInsertions); + void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len); + + bool canInsert(SourceLocation loc, FileOffset &Offset); + bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset, + SourceLocation &AfterLoc); + bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); + bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len); + bool canReplaceText(SourceLocation loc, StringRef text, + FileOffset &Offs, unsigned &Len); + + void commitInsert(FileOffset offset, StringRef text, + bool beforePreviousInsertions); + void commitRemove(FileOffset offset, unsigned length); + + bool isAtStartOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroBegin = 0) const; + bool isAtEndOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroEnd = 0) const; +}; + +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h new file mode 100644 index 0000000..c685753 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h @@ -0,0 +1,87 @@ +//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EDIT_EDITEDSOURCE_H +#define LLVM_CLANG_EDIT_EDITEDSOURCE_H + +#include "clang/Edit/FileOffset.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include <map> + +namespace clang { + class LangOptions; + class PreprocessingRecord; + +namespace edit { + class Commit; + class EditsReceiver; + +class EditedSource { + const SourceManager &SourceMgr; + const LangOptions &LangOpts; + const PreprocessingRecord *PPRec; + + struct FileEdit { + StringRef Text; + unsigned RemoveLen; + + FileEdit() : RemoveLen(0) {} + }; + + typedef std::map<FileOffset, FileEdit> FileEditsTy; + FileEditsTy FileEdits; + + llvm::DenseMap<unsigned, SourceLocation> ExpansionToArgMap; + + llvm::BumpPtrAllocator StrAlloc; + +public: + EditedSource(const SourceManager &SM, const LangOptions &LangOpts, + const PreprocessingRecord *PPRec = 0) + : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), + StrAlloc(/*size=*/512) { } + + const SourceManager &getSourceManager() const { return SourceMgr; } + const LangOptions &getLangOpts() const { return LangOpts; } + const PreprocessingRecord *getPreprocessingRecord() const { return PPRec; } + + bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); + + bool commit(const Commit &commit); + + void applyRewrites(EditsReceiver &receiver); + void clearRewrites(); + + StringRef copyString(StringRef str) { + char *buf = StrAlloc.Allocate<char>(str.size()); + std::memcpy(buf, str.data(), str.size()); + return StringRef(buf, str.size()); + } + StringRef copyString(const Twine &twine); + +private: + bool commitInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text, + bool beforePreviousInsertions); + bool commitInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, + FileOffset InsertFromRangeOffs, unsigned Len, + bool beforePreviousInsertions); + void commitRemove(SourceLocation OrigLoc, FileOffset BeginOffs, unsigned Len); + + StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs, + bool &Invalid); + FileEditsTy::iterator getActionForOffset(FileOffset Offs); +}; + +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h new file mode 100644 index 0000000..600ac28 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h @@ -0,0 +1,35 @@ +//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EDIT_EDITSRECEIVER_H +#define LLVM_CLANG_EDIT_EDITSRECEIVER_H + +#include "clang/Basic/LLVM.h" + +namespace clang { + class SourceLocation; + class CharSourceRange; + +namespace edit { + +class EditsReceiver { +public: + virtual ~EditsReceiver() { } + + virtual void insert(SourceLocation loc, StringRef text) = 0; + virtual void replace(CharSourceRange range, StringRef text) = 0; + /// \brief By default it calls replace with an empty string. + virtual void remove(CharSourceRange range); +}; + +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h new file mode 100644 index 0000000..675ad18 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h @@ -0,0 +1,65 @@ +//===----- FileOffset.h - Offset in a file ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EDIT_FILEOFFSET_H +#define LLVM_CLANG_EDIT_FILEOFFSET_H + +#include "clang/Basic/SourceLocation.h" + +namespace clang { + +namespace edit { + +class FileOffset { + FileID FID; + unsigned Offs; +public: + FileOffset() : Offs(0) { } + FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { } + + bool isInvalid() const { return FID.isInvalid(); } + + FileID getFID() const { return FID; } + unsigned getOffset() const { return Offs; } + + FileOffset getWithOffset(unsigned offset) const { + FileOffset NewOffs = *this; + NewOffs.Offs += offset; + return NewOffs; + } + + friend bool operator==(FileOffset LHS, FileOffset RHS) { + return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs; + } + friend bool operator!=(FileOffset LHS, FileOffset RHS) { + return !(LHS == RHS); + } + friend bool operator<(FileOffset LHS, FileOffset RHS) { + if (LHS.FID != RHS.FID) + return LHS.FID < RHS.FID; + return LHS.Offs < RHS.Offs; + } + friend bool operator>(FileOffset LHS, FileOffset RHS) { + if (LHS.FID != RHS.FID) + return LHS.FID > RHS.FID; + return LHS.Offs > RHS.Offs; + } + friend bool operator>=(FileOffset LHS, FileOffset RHS) { + return LHS > RHS || LHS == RHS; + } + friend bool operator<=(FileOffset LHS, FileOffset RHS) { + return LHS < RHS || LHS == RHS; + } +}; + +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h new file mode 100644 index 0000000..aa7a5b2 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h @@ -0,0 +1,33 @@ +//===--- Rewriters.h - Rewritings ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EDIT_REWRITERS_H +#define LLVM_CLANG_EDIT_REWRITERS_H + +namespace clang { + class ObjCMessageExpr; + class NSAPI; + +namespace edit { + class Commit; + +bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit); + +bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit); + +bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit); + +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h index 471476a..5e4ecad 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h @@ -20,6 +20,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/PreprocessingRecord.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" @@ -45,6 +46,7 @@ class ASTContext; class ASTReader; class CodeCompleteConsumer; class CompilerInvocation; +class CompilerInstance; class Decl; class DiagnosticsEngine; class FileEntry; @@ -57,39 +59,33 @@ class ASTFrontendAction; using namespace idx; -/// \brief Allocator for a cached set of global code completions. -class GlobalCodeCompletionAllocator - : public CodeCompletionAllocator, - public llvm::RefCountedBase<GlobalCodeCompletionAllocator> -{ - -}; - /// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit : public ModuleLoader { private: - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; - llvm::IntrusiveRefCntPtr<FileManager> FileMgr; - llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; - llvm::OwningPtr<HeaderSearch> HeaderInfo; - llvm::IntrusiveRefCntPtr<TargetInfo> Target; - llvm::IntrusiveRefCntPtr<Preprocessor> PP; - llvm::IntrusiveRefCntPtr<ASTContext> Ctx; + IntrusiveRefCntPtr<LangOptions> LangOpts; + IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + IntrusiveRefCntPtr<FileManager> FileMgr; + IntrusiveRefCntPtr<SourceManager> SourceMgr; + OwningPtr<HeaderSearch> HeaderInfo; + IntrusiveRefCntPtr<TargetInfo> Target; + IntrusiveRefCntPtr<Preprocessor> PP; + IntrusiveRefCntPtr<ASTContext> Ctx; + ASTReader *Reader; FileSystemOptions FileSystemOpts; /// \brief The AST consumer that received information about the translation /// unit as it was parsed or loaded. - llvm::OwningPtr<ASTConsumer> Consumer; + OwningPtr<ASTConsumer> Consumer; /// \brief The semantic analysis object used to type-check the translation /// unit. - llvm::OwningPtr<Sema> TheSema; + OwningPtr<Sema> TheSema; /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. - llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; + IntrusiveRefCntPtr<CompilerInvocation> Invocation; /// \brief The set of target features. /// @@ -126,6 +122,14 @@ private: // source. In the long term we should make the Index library use efficient and // more scalable search mechanisms. std::vector<Decl*> TopLevelDecls; + + /// \brief Sorted (by file offset) vector of pairs of file offset/Decl. + typedef SmallVector<std::pair<unsigned, Decl *>, 64> LocDeclsTy; + typedef llvm::DenseMap<FileID, LocDeclsTy *> FileDeclsTy; + + /// \brief Map from FileID to the file-level declarations that it contains. + /// The files and decls are only local (and non-preamble) ones. + FileDeclsTy FileDecls; /// The name of the original source file used to generate this ASTUnit. std::string OriginalSourceFile; @@ -140,6 +144,10 @@ private: /// translation unit. SmallVector<StoredDiagnostic, 4> StoredDiagnostics; + /// \brief The set of diagnostics produced when failing to parse, e.g. due + /// to failure to load the PCH. + SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics; + /// \brief The number of stored diagnostics that come from the driver /// itself. /// @@ -147,10 +155,6 @@ private: /// the next. unsigned NumStoredDiagnosticsFromDriver; - /// \brief Temporary files that should be removed when the ASTUnit is - /// destroyed. - SmallVector<llvm::sys::Path, 4> TemporaryFiles; - /// \brief Counter that determines when we want to try building a /// precompiled preamble. /// @@ -161,10 +165,7 @@ private: /// building the precompiled preamble fails, we won't try again for /// some number of calls. unsigned PreambleRebuildCounter; - - /// \brief The file in which the precompiled preamble is stored. - std::string PreambleFile; - + public: class PreambleData { const FileEntry *File; @@ -254,15 +255,11 @@ private: /// \brief Whether we should be caching code-completion results. bool ShouldCacheCodeCompletionResults; - - /// \brief Whether we want to include nested macro expansions in the - /// detailed preprocessing record. - bool NestedMacroExpansions; /// \brief The language options used when we load an AST file. LangOptions ASTFileLangOpts; - static void ConfigureDiags(llvm::IntrusiveRefCntPtr<DiagnosticsEngine> &Diags, + static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags, const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics); @@ -271,6 +268,8 @@ private: const SmallVectorImpl<StoredDiagnostic> &Diags, SmallVectorImpl<StoredDiagnostic> &Out); + void clearFileLevelDecls(); + public: /// \brief A cached code-completion result, which may be introduced in one of /// many different contexts. @@ -318,29 +317,24 @@ public: } /// \brief Retrieve the allocator used to cache global code completions. - llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> + IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> getCachedCompletionAllocator() { return CachedCompletionAllocator; } - - /// \brief Retrieve the allocator used to cache global code completions. - /// Creates the allocator if it doesn't already exist. - llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> - getCursorCompletionAllocator() { - if (!CursorCompletionAllocator.getPtr()) { - CursorCompletionAllocator = new GlobalCodeCompletionAllocator; - } - return CursorCompletionAllocator; + + CodeCompletionTUInfo &getCodeCompletionTUInfo() { + if (!CCTUInfo) + CCTUInfo.reset(new CodeCompletionTUInfo( + new GlobalCodeCompletionAllocator)); + return *CCTUInfo; } - + private: /// \brief Allocator used to store cached code completions. - llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> + IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> CachedCompletionAllocator; - /// \brief Allocator used to store code completions for arbitrary cursors. - llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> - CursorCompletionAllocator; + OwningPtr<CodeCompletionTUInfo> CCTUInfo; /// \brief The set of cached code-completion results. std::vector<CachedCodeCompletionResult> CachedCompletionResults; @@ -395,7 +389,11 @@ private: bool AllowRebuild = true, unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); - + + /// \brief Transfers ownership of the objects (like SourceManager) from + /// \param CI to this ASTUnit. + void transferASTDataFromCompilerInstance(CompilerInstance &CI); + /// \brief Allows us to assert that ASTUnit is not being used concurrently, /// which is not supported. /// @@ -451,6 +449,7 @@ public: ASTContext &getASTContext() { return *Ctx; } void setASTContext(ASTContext *ctx) { Ctx = ctx; } + void setPreprocessor(Preprocessor *pp); bool hasSema() const { return TheSema; } Sema &getSema() const { @@ -468,9 +467,7 @@ public: /// \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); - } + void addTemporaryFile(const llvm::sys::Path &TempFile); bool getOnlyLocalDecls() const { return OnlyLocalDecls; } @@ -514,6 +511,15 @@ public: TopLevelDecls.push_back(D); } + /// \brief Add a new local file-level declaration. + void addFileLevelDecl(Decl *D); + + /// \brief Get the decls that are contained in a file in the Offset/Length + /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// a range. + void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, + SmallVectorImpl<Decl *> &Decls); + /// \brief Add a new top-level declaration, identified by its ID in /// the precompiled preamble. void addTopLevelDeclFromPreamble(serialization::DeclID D) { @@ -546,6 +552,11 @@ public: /// preamble, otherwise it returns \arg Loc. SourceLocation mapLocationToPreamble(SourceLocation Loc); + bool isInPreambleFileID(SourceLocation Loc); + bool isInMainFileID(SourceLocation Loc); + SourceLocation getStartOfMainFileID(); + SourceLocation getEndOfPreambleFileID(); + /// \brief \see mapLocationFromPreamble. SourceRange mapRangeFromPreamble(SourceRange R) { return SourceRange(mapLocationFromPreamble(R.getBegin()), @@ -559,17 +570,26 @@ public: } // Retrieve the diagnostics associated with this AST - typedef const StoredDiagnostic *stored_diag_iterator; - stored_diag_iterator stored_diag_begin() const { + typedef StoredDiagnostic *stored_diag_iterator; + typedef const StoredDiagnostic *stored_diag_const_iterator; + stored_diag_const_iterator stored_diag_begin() const { + return StoredDiagnostics.begin(); + } + stored_diag_iterator stored_diag_begin() { return StoredDiagnostics.begin(); } - stored_diag_iterator stored_diag_end() const { + stored_diag_const_iterator stored_diag_end() const { + return StoredDiagnostics.end(); + } + stored_diag_iterator stored_diag_end() { return StoredDiagnostics.end(); } unsigned stored_diag_size() const { return StoredDiagnostics.size(); } - - SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() { - return StoredDiagnostics; + + stored_diag_iterator stored_diag_afterDriver_begin() { + if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size()) + NumStoredDiagnosticsFromDriver = 0; + return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; } typedef std::vector<CachedCodeCompletionResult>::iterator @@ -601,7 +621,8 @@ public: /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static ASTUnit *create(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + bool CaptureDiagnostics = false); /// \brief Create a ASTUnit from an AST file. /// @@ -612,12 +633,13 @@ public: /// /// \returns - The initialized ASTUnit or null if the AST failed to load. static ASTUnit *LoadFromASTFile(const std::string &Filename, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics = false, + bool AllowPCHWithCompilerErrors = false); private: /// \brief Helper function for \c LoadFromCompilerInvocation() and @@ -646,10 +668,28 @@ public: /// /// \param Unit - optionally an already created ASTUnit. Its ownership is not /// transfered. + /// + /// \param Persistent - if true the returned ASTUnit will be complete. + /// false means the caller is only interested in getting info through the + /// provided \see Action. + /// + /// \param ErrAST - If non-null and parsing failed without any AST to return + /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit + /// mainly to allow the caller to see the diagnostics. + /// This will only receive an ASTUnit if a new one was created. If an already + /// created ASTUnit was passed in \param Unit then the caller can check that. + /// static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action = 0, - ASTUnit *Unit = 0); + ASTUnit *Unit = 0, + bool Persistent = true, + StringRef ResourceFilesPath = StringRef(), + bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CacheCodeCompletionResults = false, + OwningPtr<ASTUnit> *ErrAST = 0); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a /// CompilerInvocation object. @@ -663,13 +703,12 @@ public: // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, - bool CacheCodeCompletionResults = false, - bool NestedMacroExpansions = true); + bool CacheCodeCompletionResults = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -682,12 +721,16 @@ public: /// lifetime is expected to extend past that of the returned ASTUnit. /// /// \param ResourceFilesPath - The path to the compiler resource files. - // + /// + /// \param ErrAST - If non-null and parsing failed without any AST to return + /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit + /// mainly to allow the caller to see the diagnostics. + /// // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, @@ -697,7 +740,9 @@ public: bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, - bool NestedMacroExpansions = true); + bool AllowPCHWithCompilerErrors = false, + bool SkipFunctionBodies = false, + OwningPtr<ASTUnit> *ErrAST = 0); /// \brief Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. @@ -743,9 +788,9 @@ public: /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); - virtual ModuleKey loadModule(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc) { + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) { // ASTUnit doesn't know how to load modules (not that this matters). return 0; } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def index 010f889..b5b9394 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def @@ -30,6 +30,7 @@ ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of conc ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false) ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true) +ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true) ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true) ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true) @@ -41,8 +42,24 @@ ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraint ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") +#ifndef ANALYSIS_IPA +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") +ANALYSIS_IPA(Inlining, "inlining", "Experimental: Inline callees when their definitions are available") + +#ifndef ANALYSIS_INLINING_MODE +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions in the order defined in the TU") +ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined, use call graph to order") + #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS #undef ANALYSIS_PURGE +#undef ANALYSIS_INLINING_MODE +#undef ANALYSIS_IPA diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h index 3565a51..847bfbd 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h @@ -60,6 +60,20 @@ enum AnalysisPurgeMode { NumPurgeModes }; +/// AnalysisIPAMode - Set of inter-procedural modes. +enum AnalysisIPAMode { +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) NAME, +#include "clang/Frontend/Analyses.def" +NumIPAModes +}; + +/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. +enum AnalysisInliningMode { +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, +#include "clang/Frontend/Analyses.def" +NumInliningModes +}; + class AnalyzerOptions { public: /// \brief Pair of checker name and enable/disable. @@ -68,6 +82,7 @@ public: AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; AnalysisPurgeMode AnalysisPurgeOpt; + AnalysisIPAMode IPAMode; std::string AnalyzeSpecificFunction; unsigned MaxNodes; unsigned MaxLoop; @@ -79,11 +94,15 @@ public: unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; - unsigned InlineCall : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; unsigned CFGAddInitializers : 1; unsigned EagerlyTrimEGraph : 1; + unsigned PrintStats : 1; + unsigned NoRetryExhausted : 1; + unsigned InlineMaxStackDepth; + unsigned InlineMaxFunctionSize; + AnalysisInliningMode InliningMode; public: AnalyzerOptions() { @@ -91,6 +110,7 @@ public: AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagOpt = PD_HTML; AnalysisPurgeOpt = PurgeStmt; + IPAMode = Inlining; ShowCheckerHelp = 0; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; @@ -99,11 +119,16 @@ public: TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; - InlineCall = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; CFGAddInitializers = 0; EagerlyTrimEGraph = 0; + PrintStats = 0; + NoRetryExhausted = 0; + // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). + InlineMaxStackDepth = 5; + InlineMaxFunctionSize = 200; + InliningMode = NoRedundancy; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h index f20cf6f..ce2b242 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -21,8 +21,9 @@ class LangOptions; /// should be the "primary" client, and will be used for computing whether the /// diagnostics should be included in counts. class ChainedDiagnosticConsumer : public DiagnosticConsumer { - llvm::OwningPtr<DiagnosticConsumer> Primary; - llvm::OwningPtr<DiagnosticConsumer> Secondary; + virtual void anchor(); + OwningPtr<DiagnosticConsumer> Primary; + OwningPtr<DiagnosticConsumer> Secondary; public: ChainedDiagnosticConsumer(DiagnosticConsumer *_Primary, @@ -42,6 +43,11 @@ public: Primary->EndSourceFile(); } + virtual void finish() { + Secondary->finish(); + Primary->finish(); + } + virtual bool IncludeInDiagnosticCounts() const { return Primary->IncludeInDiagnosticCounts(); } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ChainedIncludesSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedIncludesSource.h index 620dbdf..d7119e9 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ChainedIncludesSource.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedIncludesSource.h @@ -30,7 +30,7 @@ private: ExternalSemaSource &getFinalReader() const { return *FinalReader; } std::vector<CompilerInstance *> CIs; - llvm::OwningPtr<ExternalSemaSource> FinalReader; + OwningPtr<ExternalSemaSource> FinalReader; protected: @@ -66,7 +66,7 @@ protected: virtual void InitializeSema(Sema &S); virtual void ForgetSema(); - virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); virtual bool LookupUnqualified(LookupResult &R, Scope *S); }; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h index 4874c17..e844f88 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -50,6 +50,7 @@ public: /// internal state before optimizations are /// done. unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. + unsigned DisableTailCalls : 1; /// Do not emit tail calls. unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what /// Decl* various IR entities came from. Only /// useful when running CodeGen as a @@ -71,10 +72,14 @@ public: unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled. + unsigned NoDwarfDirectoryAsm : 1; /// Set when -fno-dwarf-directory-asm is + /// enabled. unsigned NoExecStack : 1; /// Set when -Wa,--noexecstack is enabled. unsigned NoGlobalMerge : 1; /// Set when -mno-global-merge is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf. + unsigned NoInline : 1; /// Set when -fno-inline is enabled. Disables + /// use of the inline keyword. unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. @@ -89,6 +94,7 @@ public: unsigned SaveTempLabels : 1; /// Save temporary labels. unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled. unsigned SoftFloat : 1; /// -soft-float. + unsigned StrictEnums : 1; /// Optimize based on strict enum definition. unsigned TimePasses : 1; /// Set when -ftime-report is enabled. unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization /// selection. @@ -103,6 +109,11 @@ public: unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. + unsigned StackRealignment : 1; /// Control whether to permit stack + /// realignment. + unsigned StackAlignment; /// Overrides default stack alignment, + /// if not 0. + /// The code model to use (-mcmodel). std::string CodeModel; @@ -113,6 +124,9 @@ public: /// Enable additional debugging information. std::string DebugPass; + /// The string to embed in debug information as the current working directory. + std::string DebugCompilationDir; + /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; @@ -123,6 +137,9 @@ public: /// The float precision limit to use, if non-empty. std::string LimitFloatPrecision; + /// The name of the bitcode file to link before optzns. + std::string LinkBitcodeFile; + /// The kind of inlining to perform. InliningMethod Inlining; @@ -134,6 +151,10 @@ public: /// The name of the relocation model to use. std::string RelocationModel; + /// If not an empty string, trap intrinsics are lowered to calls to this + /// function instead of to trap instructions. + std::string TrapFuncName; + /// A list of command-line options to forward to the LLVM backend. std::vector<std::string> BackendOptions; @@ -153,6 +174,7 @@ public: DisableFPElim = 0; DisableLLVMOpts = 0; DisableRedZone = 0; + DisableTailCalls = 0; EmitDeclMetadata = 0; EmitGcovArcs = 0; EmitGcovNotes = 0; @@ -168,6 +190,7 @@ public: NoDwarf2CFIAsm = 0; NoImplicitFloat = 0; NoInfsFPMath = 0; + NoInline = 0; NoNaNsFPMath = 0; NoZeroInitializedInBSS = 0; NumRegisterParameters = 0; @@ -183,6 +206,7 @@ public: SaveTempLabels = 0; SimplifyLibCalls = 1; SoftFloat = 0; + StrictEnums = 0; TimePasses = 0; UnitAtATime = 1; UnrollLoops = 0; @@ -190,6 +214,8 @@ public: UnwindTables = 0; UseRegisterSizedBitfieldAccess = 0; VerifyModule = 1; + StackRealignment = 0; + StackAlignment = 0; Inlining = NoInlining; RelocationModel = "pic"; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h index 8817740..1bb7695 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h @@ -11,13 +11,17 @@ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/ModuleLoader.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include <cassert> #include <list> #include <string> +#include <utility> namespace llvm { class raw_fd_ostream; @@ -32,8 +36,10 @@ class CodeCompleteConsumer; class DiagnosticsEngine; class DiagnosticConsumer; class ExternalASTSource; +class FileEntry; class FileManager; class FrontendAction; +class Module; class Preprocessor; class Sema; class SourceManager; @@ -59,41 +65,53 @@ class TargetInfo; /// and a long form that takes explicit instances of any required objects. class CompilerInstance : public ModuleLoader { /// The options used in this compiler instance. - llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; + IntrusiveRefCntPtr<CompilerInvocation> Invocation; /// The diagnostics engine instance. - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; /// The target being compiled for. - llvm::IntrusiveRefCntPtr<TargetInfo> Target; + IntrusiveRefCntPtr<TargetInfo> Target; /// The file manager. - llvm::IntrusiveRefCntPtr<FileManager> FileMgr; + IntrusiveRefCntPtr<FileManager> FileMgr; /// The source manager. - llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; + IntrusiveRefCntPtr<SourceManager> SourceMgr; /// The preprocessor. - llvm::IntrusiveRefCntPtr<Preprocessor> PP; + IntrusiveRefCntPtr<Preprocessor> PP; /// The AST context. - llvm::IntrusiveRefCntPtr<ASTContext> Context; + IntrusiveRefCntPtr<ASTContext> Context; /// The AST consumer. - llvm::OwningPtr<ASTConsumer> Consumer; + OwningPtr<ASTConsumer> Consumer; /// The code completion consumer. - llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer; + OwningPtr<CodeCompleteConsumer> CompletionConsumer; /// \brief The semantic analysis object. - llvm::OwningPtr<Sema> TheSema; + OwningPtr<Sema> TheSema; /// \brief The frontend timer - llvm::OwningPtr<llvm::Timer> FrontendTimer; + OwningPtr<llvm::Timer> FrontendTimer; /// \brief Non-owning reference to the ASTReader, if one exists. ASTReader *ModuleManager; + /// \brief The set of top-level modules that has already been loaded, + /// along with the module map + llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules; + + /// \brief The location of the module-import keyword for the last module + /// import. + SourceLocation LastModuleImportLoc; + + /// \brief The result of the last module import. + /// + Module *LastModuleImportResult; + /// \brief Holds information about the output file. /// /// If TempFilename is not empty we must rename it to Filename at the end. @@ -218,10 +236,10 @@ public: } LangOptions &getLangOpts() { - return Invocation->getLangOpts(); + return *Invocation->getLangOpts(); } const LangOptions &getLangOpts() const { - return Invocation->getLangOpts(); + return *Invocation->getLangOpts(); } PreprocessorOptions &getPreprocessorOpts() { @@ -491,7 +509,7 @@ public: /// used by some diagnostics printers (for logging purposes only). /// /// \return The new object on success, or null on failure. - static llvm::IntrusiveRefCntPtr<DiagnosticsEngine> + static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, DiagnosticConsumer *Client = 0, @@ -517,6 +535,7 @@ public: void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, bool DisableStatCache, + bool AllowPCHWithCompilerErrors, void *DeserializationListener); /// Create an external AST source to read a PCH file. @@ -526,6 +545,7 @@ public: createPCHExternalASTSource(StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, bool DisableStatCache, + bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, void *DeserializationListener, bool Preamble); @@ -554,6 +574,10 @@ public: /// Create the default output file (from the invocation's options) and add it /// to the list of tracked output files. /// + /// The files created by this function always use temporary files to write to + /// their result (that is, the data is written to a temporary file which will + /// atomically replace the target output on success). + /// /// \return - Null on error. llvm::raw_fd_ostream * createDefaultOutputFile(bool Binary = true, StringRef BaseInput = "", @@ -568,7 +592,8 @@ public: bool Binary = true, bool RemoveFileOnSignal = true, StringRef BaseInput = "", StringRef Extension = "", - bool UseTemporary = false); + bool UseTemporary = false, + bool CreateMissingDirectories = false); /// Create a new output file, optionally deriving the output path name. /// @@ -588,7 +613,9 @@ public: /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for /// multithreaded use, as the underlying signal mechanism is not reentrant /// \param UseTemporary - Create a new temporary file that must be renamed to - /// OutputPath in the end + /// OutputPath in the end. + /// \param CreateMissingDirectories - When \arg UseTemporary is true, create + /// missing directories in the output path. /// \param ResultPathName [out] - If given, the result path name will be /// stored here on success. /// \param TempPathName [out] - If given, the temporary file path name @@ -599,6 +626,7 @@ public: StringRef BaseInput = "", StringRef Extension = "", bool UseTemporary = false, + bool CreateMissingDirectories = false, std::string *ResultPathName = 0, std::string *TempPathName = 0); @@ -610,23 +638,25 @@ public: /// as the main file. /// /// \return True on success. - bool InitializeSourceManager(StringRef InputFile); + bool InitializeSourceManager(StringRef InputFile, + SrcMgr::CharacteristicKind Kind = SrcMgr::C_User); /// InitializeSourceManager - Initialize the source manager to set InputFile /// as the main file. /// /// \return True on success. static bool InitializeSourceManager(StringRef InputFile, - DiagnosticsEngine &Diags, - FileManager &FileMgr, - SourceManager &SourceMgr, - const FrontendOptions &Opts); + SrcMgr::CharacteristicKind Kind, + DiagnosticsEngine &Diags, + FileManager &FileMgr, + SourceManager &SourceMgr, + const FrontendOptions &Opts); /// } - virtual ModuleKey loadModule(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc); + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective); }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h index 47c7031..0d2260a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h @@ -14,6 +14,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Frontend/AnalyzerOptions.h" +#include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/DiagnosticOptions.h" @@ -30,18 +31,45 @@ namespace clang { +class CompilerInvocation; class DiagnosticsEngine; +namespace driver { +class ArgList; +} + +/// CompilerInvocation - Fill out Opts based on the options given in Args. +/// Args must have been created from the OptTable returned by +/// createCC1OptTable(). When errors are encountered, return false and, +/// if Diags is non-null, report the error(s). +bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args, + DiagnosticsEngine *Diags = 0); + +class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> { +protected: + /// Options controlling the language variant. + IntrusiveRefCntPtr<LangOptions> LangOpts; +public: + CompilerInvocationBase(); + + CompilerInvocationBase(const CompilerInvocationBase &X); + + LangOptions *getLangOpts() { return LangOpts.getPtr(); } + const LangOptions *getLangOpts() const { return LangOpts.getPtr(); } +}; + /// CompilerInvocation - Helper class for holding the data necessary to invoke /// the compiler. /// /// This class is designed to represent an abstract "invocation" of the /// compiler, including data such as the include paths, the code generation /// options, the warning flags, and so on. -class CompilerInvocation : public llvm::RefCountedBase<CompilerInvocation> { +class CompilerInvocation : public CompilerInvocationBase { /// Options controlling the static analyzer. AnalyzerOptions AnalyzerOpts; + MigratorOptions MigratorOpts; + /// Options controlling IRgen and the backend. CodeGenOptions CodeGenOpts; @@ -60,9 +88,6 @@ class CompilerInvocation : public llvm::RefCountedBase<CompilerInvocation> { /// Options controlling the #include directive. HeaderSearchOptions HeaderSearchOpts; - /// Options controlling the language variant. - LangOptions LangOpts; - /// Options controlling the preprocessor (aside from #include handling). PreprocessorOptions PreprocessorOpts; @@ -79,13 +104,13 @@ public: /// @{ /// CreateFromArgs - Create a compiler invocation from a list of input - /// options. + /// options. Returns true on success. /// /// \param Res [out] - The resulting invocation. /// \param ArgBegin - The first element in the argument vector. /// \param ArgEnd - The last element in the argument vector. /// \param Diags - The diagnostic engine to use for errors. - static void CreateFromArgs(CompilerInvocation &Res, + static bool CreateFromArgs(CompilerInvocation &Res, const char* const *ArgBegin, const char* const *ArgEnd, DiagnosticsEngine &Diags); @@ -111,7 +136,7 @@ public: /// \param LangStd - The input language standard. void setLangDefaults(InputKind IK, LangStandard::Kind LangStd = LangStandard::lang_unspecified) { - setLangDefaults(LangOpts, IK, LangStd); + setLangDefaults(*getLangOpts(), IK, LangStd); } /// setLangDefaults - Set language defaults for the given input language and @@ -136,6 +161,11 @@ public: return AnalyzerOpts; } + MigratorOptions &getMigratorOpts() { return MigratorOpts; } + const MigratorOptions &getMigratorOpts() const { + return MigratorOpts; + } + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; @@ -166,9 +196,6 @@ public: return FrontendOpts; } - LangOptions &getLangOpts() { return LangOpts; } - const LangOptions &getLangOpts() const { return LangOpts; } - PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; } const PreprocessorOptions &getPreprocessorOpts() const { return PreprocessorOpts; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h index 1e22c22..83976c3 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h @@ -25,7 +25,7 @@ public: /// dependency, which can avoid some 'make' /// problems. unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list - + /// The file to write dependency output to. std::string OutputFile; @@ -39,6 +39,9 @@ public: /// must contain at least one entry. std::vector<std::string> Targets; + /// \brief The file to write GraphViz-formatted header dependencies to. + std::string DOTOutputFile; + public: DependencyOutputOptions() { IncludeSystemHeaders = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h index 319abeb..1c6ba6a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h @@ -31,7 +31,6 @@ public: unsigned ShowFixits : 1; /// Show fixit information. unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its. - unsigned ShowNames : 1; /// Show the diagnostic name unsigned ShowOptionNames : 1; /// Show the option name for mappable /// diagnostics. unsigned ShowNoteIncludeStack : 1; /// Show include stacks for notes. @@ -51,12 +50,14 @@ public: unsigned ErrorLimit; /// Limit # errors emitted. unsigned MacroBacktraceLimit; /// Limit depth of macro expansion backtrace. unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. + unsigned ConstexprBacktraceLimit; /// Limit depth of constexpr backtrace. /// The distance between tab stops. unsigned TabStop; enum { DefaultTabStop = 8, MaxTabStop = 100, DefaultMacroBacktraceLimit = 6, - DefaultTemplateBacktraceLimit = 10 }; + DefaultTemplateBacktraceLimit = 10, + DefaultConstexprBacktraceLimit = 10 }; /// Column limit for formatting message diagnostics, or 0 if unused. unsigned MessageLength; @@ -67,6 +68,9 @@ public: /// The file to log diagnostic output to. std::string DiagnosticLogFile; + + /// The file to serialize diagnostics to (non-appending). + std::string DiagnosticSerializationFile; /// The list of -W... options used to alter the diagnostic mappings, with the /// prefixes removed. @@ -86,7 +90,6 @@ public: ShowColumn = 1; ShowFixits = 1; ShowLocation = 1; - ShowNames = 0; ShowOptionNames = 0; ShowCategories = 0; Format = Clang; @@ -96,6 +99,7 @@ public: ErrorLimit = 0; TemplateBacktraceLimit = DefaultTemplateBacktraceLimit; MacroBacktraceLimit = DefaultMacroBacktraceLimit; + ConstexprBacktraceLimit = DefaultConstexprBacktraceLimit; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h new file mode 100644 index 0000000..5ad88a8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h @@ -0,0 +1,149 @@ +//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a utility class that provides support for pretty-printing of +// diagnostics. It is used to implement the different code paths which require +// such functionality in a consistent way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ +#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + +class DiagnosticOptions; +class LangOptions; +class SourceManager; + +typedef llvm::PointerUnion<const Diagnostic *, + const StoredDiagnostic *> DiagOrStoredDiag; + +/// \brief Class to encapsulate the logic for formatting a diagnostic message. +/// Actual "printing" logic is implemented by subclasses. +/// +/// This class provides an interface for building and emitting +/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt +/// Hints, and code snippets. In the presence of macros this involves +/// a recursive process, synthesizing notes for each macro expansion. +/// +/// A brief worklist: +/// FIXME: Sink the recursive printing of template instantiations into this +/// class. +class DiagnosticRenderer { +protected: + const SourceManager &SM; + const LangOptions &LangOpts; + const DiagnosticOptions &DiagOpts; + + /// \brief The location of the previous diagnostic if known. + /// + /// This will be invalid in cases where there is no (known) previous + /// diagnostic location, or that location itself is invalid or comes from + /// a different source manager than SM. + SourceLocation LastLoc; + + /// \brief The location of the last include whose stack was printed if known. + /// + /// Same restriction as \see LastLoc essentially, but tracking include stack + /// root locations rather than diagnostic locations. + SourceLocation LastIncludeLoc; + + /// \brief The level of the last diagnostic emitted. + /// + /// The level of the last diagnostic emitted. Used to detect level changes + /// which change the amount of information displayed. + DiagnosticsEngine::Level LastLevel; + + DiagnosticRenderer(const SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticOptions &DiagOpts); + + virtual ~DiagnosticRenderer(); + + virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<CharSourceRange> Ranges, + DiagOrStoredDiag Info) = 0; + + virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges) = 0; + + virtual void emitBasicNote(StringRef Message) = 0; + + virtual void emitCodeContext(SourceLocation Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints) = 0; + + virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0; + + virtual void beginDiagnostic(DiagOrStoredDiag D, + DiagnosticsEngine::Level Level) {} + virtual void endDiagnostic(DiagOrStoredDiag D, + DiagnosticsEngine::Level Level) {} + + +private: + void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level); + void emitIncludeStackRecursively(SourceLocation Loc); + void emitMacroExpansionsAndCarets(SourceLocation Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints, + unsigned &MacroDepth, + unsigned OnMacroInst = 0); +public: + /// \brief Emit a diagnostic. + /// + /// This is the primary entry point for emitting diagnostic messages. + /// It handles formatting and rendering the message as well as any ancillary + /// information needed based on macros whose expansions impact the + /// diagnostic. + /// + /// \param Loc The location for this caret. + /// \param Level The level of the diagnostic to be emitted. + /// \param Message The diagnostic message to emit. + /// \param Ranges The underlined ranges for this code snippet. + /// \param FixItHints The FixIt hints active for this diagnostic. + void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> FixItHints, + DiagOrStoredDiag D = (Diagnostic *)0); + + void emitStoredDiagnostic(StoredDiagnostic &Diag); +}; + +/// Subclass of DiagnosticRender that turns all subdiagostics into explicit +/// notes. It is up to subclasses to further define the behavior. +class DiagnosticNoteRenderer : public DiagnosticRenderer { +public: + DiagnosticNoteRenderer(const SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticOptions &DiagOpts) + : DiagnosticRenderer(SM, LangOpts, DiagOpts) {} + + virtual ~DiagnosticNoteRenderer(); + + virtual void emitBasicNote(StringRef Message); + + virtual void emitIncludeLocation(SourceLocation Loc, + PresumedLoc PLoc); + + virtual void emitNote(SourceLocation Loc, StringRef Message) = 0; +}; +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h index f85cc7e..6839028 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h @@ -12,6 +12,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include <string> @@ -23,30 +24,11 @@ class ASTMergeAction; class ASTUnit; class CompilerInstance; -enum InputKind { - IK_None, - IK_Asm, - IK_C, - IK_CXX, - IK_ObjC, - IK_ObjCXX, - IK_PreprocessedC, - IK_PreprocessedCXX, - IK_PreprocessedObjC, - IK_PreprocessedObjCXX, - IK_OpenCL, - IK_CUDA, - IK_AST, - IK_LLVM_IR -}; - - /// FrontendAction - Abstract base class for actions which can be performed by /// the frontend. class FrontendAction { - std::string CurrentFile; - InputKind CurrentFileKind; - llvm::OwningPtr<ASTUnit> CurrentASTUnit; + FrontendInputFile CurrentInput; + OwningPtr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; friend class ASTMergeAction; friend class WrapperFrontendAction; @@ -103,7 +85,7 @@ protected: /// EndSourceFileAction - Callback at the end of processing a single input; /// this is guaranteed to only be called following a successful call to - /// BeginSourceFileAction (and BeingSourceFile). + /// BeginSourceFileAction (and BeginSourceFile). virtual void EndSourceFileAction() {} /// @} @@ -127,18 +109,22 @@ public: /// @{ bool isCurrentFileAST() const { - assert(!CurrentFile.empty() && "No current file!"); + assert(!CurrentInput.File.empty() && "No current file!"); return CurrentASTUnit != 0; } + const FrontendInputFile &getCurrentInput() const { + return CurrentInput; + } + const std::string &getCurrentFile() const { - assert(!CurrentFile.empty() && "No current file!"); - return CurrentFile; + assert(!CurrentInput.File.empty() && "No current file!"); + return CurrentInput.File; } InputKind getCurrentFileKind() const { - assert(!CurrentFile.empty() && "No current file!"); - return CurrentFileKind; + assert(!CurrentInput.File.empty() && "No current file!"); + return CurrentInput.Kind; } ASTUnit &getCurrentASTUnit() const { @@ -150,7 +136,7 @@ public: return CurrentASTUnit.take(); } - void setCurrentFile(StringRef Value, InputKind Kind, ASTUnit *AST = 0); + void setCurrentInput(const FrontendInputFile &CurrentInput, ASTUnit *AST = 0); /// @} /// @name Supported Modes @@ -189,10 +175,7 @@ public: /// action may store and use this object up until the matching EndSourceFile /// action. /// - /// \param Filename - The input filename, which will be made available to - /// clients via \see getCurrentFile(). - /// - /// \param InputKind - The type of input. Some input kinds are handled + /// \param Input - The input filename and kind. Some input kinds are handled /// specially, for example AST inputs, since the AST file itself contains /// several objects which would normally be owned by the /// CompilerInstance. When processing AST input files, these objects should @@ -200,10 +183,9 @@ public: /// automatically be shared with the AST file in between \see /// BeginSourceFile() and \see EndSourceFile(). /// - /// \return True on success; the compilation of this file should be aborted - /// and neither Execute nor EndSourceFile should be called. - bool BeginSourceFile(CompilerInstance &CI, StringRef Filename, - InputKind Kind); + /// \return True on success; on failure the compilation of this file should + /// be aborted and neither Execute nor EndSourceFile should be called. + bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); /// Execute - Set the source managers main input file, and run the action. void Execute(); @@ -231,6 +213,7 @@ public: }; class PluginASTAction : public ASTFrontendAction { + virtual void anchor(); protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) = 0; @@ -265,7 +248,7 @@ public: /// implements every virtual method in the FrontendAction interface by /// forwarding to the wrapped action. class WrapperFrontendAction : public FrontendAction { - llvm::OwningPtr<FrontendAction> WrappedAction; + OwningPtr<FrontendAction> WrappedAction; protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h index 72a3d90..8817c5a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h @@ -16,6 +16,8 @@ namespace clang { +class Module; + //===----------------------------------------------------------------------===// // Custom Consumer Actions //===----------------------------------------------------------------------===// @@ -67,22 +69,17 @@ protected: }; class GeneratePCHAction : public ASTFrontendAction { - bool MakeModule; - protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile); - virtual TranslationUnitKind getTranslationUnitKind() { - return MakeModule? TU_Module : TU_Prefix; + virtual TranslationUnitKind getTranslationUnitKind() { + return TU_Prefix; } virtual bool hasASTFileSupport() const { return false; } public: - /// \brief Create a new action - explicit GeneratePCHAction(bool MakeModule) : MakeModule(MakeModule) { } - /// \brief Compute the AST consumer arguments that will be used to /// create the PCHGenerator instance returned by CreateASTConsumer. /// @@ -94,6 +91,33 @@ public: raw_ostream *&OS); }; +class GenerateModuleAction : public ASTFrontendAction { + clang::Module *Module; + +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + + virtual TranslationUnitKind getTranslationUnitKind() { + return TU_Module; + } + + virtual bool hasASTFileSupport() const { return false; } + +public: + virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename); + + /// \brief Compute the AST consumer arguments that will be used to + /// create the PCHGenerator instance returned by CreateASTConsumer. + /// + /// \returns true if an error occurred, false otherwise. + static bool ComputeASTConsumerArguments(CompilerInstance &CI, + StringRef InFile, + std::string &Sysroot, + std::string &OutputFile, + raw_ostream *&OS); +}; + class SyntaxOnlyAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, @@ -129,8 +153,7 @@ protected: virtual void EndSourceFileAction(); public: - ASTMergeAction(FrontendAction *AdaptedAction, - std::string *ASTFiles, unsigned NumASTFiles); + ASTMergeAction(FrontendAction *AdaptedAction, ArrayRef<std::string> ASTFiles); virtual ~ASTMergeAction(); virtual bool usesPreprocessorOnly() const; @@ -150,6 +173,15 @@ protected: virtual bool usesPreprocessorOnly() const { return true; } }; +class PubnamesDumpAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + +public: + virtual bool hasCodeCompletionSupport() const { return false; } +}; + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h index 21cd2c6..0b05b74 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define FRONTENDSTART #include "clang/Basic/DiagnosticFrontendKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h index fa6d044..a051d7f 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h @@ -11,7 +11,6 @@ #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #include "clang/Frontend/CommandLineSourceLoc.h" -#include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/StringRef.h" #include <string> #include <vector> @@ -43,14 +42,50 @@ namespace frontend { PrintDeclContext, ///< Print DeclContext and their Decls. PrintPreamble, ///< Print the "preamble" of the input file PrintPreprocessedInput, ///< -E mode. + PubnamesDump, ///< Print all of the "public" names in the source. RewriteMacros, ///< Expand macros but not #includes. RewriteObjC, ///< ObjC->C Rewriter. RewriteTest, ///< Rewriter playground RunAnalysis, ///< Run one or more source code analyses. + MigrateSource, ///< Run migrator. RunPreprocessorOnly ///< Just lex, no output. }; } +enum InputKind { + IK_None, + IK_Asm, + IK_C, + IK_CXX, + IK_ObjC, + IK_ObjCXX, + IK_PreprocessedC, + IK_PreprocessedCXX, + IK_PreprocessedObjC, + IK_PreprocessedObjCXX, + IK_OpenCL, + IK_CUDA, + IK_AST, + IK_LLVM_IR +}; + + +/// \brief An input file for the front end. +struct FrontendInputFile { + /// \brief The file name, or "-" to read from standard input. + std::string File; + + /// \brief The kind of input, e.g., C source, AST file, LLVM IR. + InputKind Kind; + + /// \brief Whether we're dealing with a 'system' input (vs. a 'user' input). + bool IsSystem; + + FrontendInputFile() : Kind(IK_None) { } + FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) + : File(File.str()), Kind(Kind), IsSystem(IsSystem) { } +}; + /// FrontendOptions - Options for controlling the behavior of the frontend. class FrontendOptions { public: @@ -72,8 +107,15 @@ public: unsigned ShowVersion : 1; ///< Show the -version text. unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are /// unfixable errors. + unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings. + unsigned FixAndRecompile : 1; ///< Apply fixes and recompile. + unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files. unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the /// migrator can fix them + unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to + /// speed up parsing in cases you do + /// not need them (e.g. with code + /// completion). enum { ARCMT_None, @@ -82,11 +124,20 @@ public: ARCMT_Migrate } ARCMTAction; - std::string ARCMTMigrateDir; + enum { + ObjCMT_None = 0, + /// \brief Enable migration to modern ObjC literals. + ObjCMT_Literals = 0x1, + /// \brief Enable migration to modern ObjC subscripting. + ObjCMT_Subscripting = 0x2 + }; + unsigned ObjCMTAction; + + std::string MTMigrateDir; std::string ARCMTMigrateReportOut; /// The input files and their types. - std::vector<std::pair<InputKind, std::string> > Inputs; + std::vector<FrontendInputFile> Inputs; /// The output file, if any. std::string OutputFile; @@ -122,6 +173,10 @@ public: /// should only be used for debugging and experimental features. std::vector<std::string> LLVMArgs; + /// \brief File name of the file that will provide record layouts + /// (in the format produced by -fdump-record-layouts). + std::string OverrideRecordLayoutsFile; + public: FrontendOptions() { DisableFree = 0; @@ -137,6 +192,8 @@ public: ShowVersion = 0; ARCMTAction = ARCMT_None; ARCMTMigrateEmitARCErrors = 0; + SkipFunctionBodies = 0; + ObjCMTAction = ObjCMT_None; } /// getInputKindForExtension - Return the appropriate input kind for a file diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h index de2800c..e6f4403 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h @@ -21,7 +21,7 @@ enum LangFeatures { BCPLComment = (1 << 0), C89 = (1 << 1), C99 = (1 << 2), - C1X = (1 << 3), + C11 = (1 << 3), CPlusPlus = (1 << 4), CPlusPlus0x = (1 << 5), Digraphs = (1 << 6), @@ -62,8 +62,8 @@ public: /// isC99 - Language is a superset of C99. bool isC99() const { return Flags & frontend::C99; } - /// isC1X - Language is a superset of C1X. - bool isC1X() const { return Flags & frontend::C1X; } + /// isC11 - Language is a superset of C11. + bool isC11() const { return Flags & frontend::C11; } /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def index c82290b..4bcff4a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def @@ -62,17 +62,26 @@ LANGSTANDARD(gnu9x, "gnu9x", "ISO C 1999 with GNU extensions", BCPLComment | C99 | Digraphs | GNUMode | HexFloat) -// C1X modes +// C11 modes +LANGSTANDARD(c11, "c11", + "ISO C 2011", + BCPLComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(c1x, "c1x", - "ISO C 201X", - BCPLComment | C99 | C1X | Digraphs | HexFloat) + "ISO C 2011", + BCPLComment | C99 | C11 | Digraphs | HexFloat) +LANGSTANDARD(iso9899_2011, + "iso9899:2011", "ISO C 2011", + BCPLComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(iso9899_201x, - "iso9899:201x", "ISO C 201X", - BCPLComment | C99 | C1X | Digraphs | HexFloat) + "iso9899:2011", "ISO C 2011", + BCPLComment | C99 | C11 | Digraphs | HexFloat) +LANGSTANDARD(gnu11, "gnu11", + "ISO C 2011 with GNU extensions", + BCPLComment | C99 | C11 | Digraphs | GNUMode | HexFloat) LANGSTANDARD(gnu1x, "gnu1x", - "ISO C 201X with GNU extensions", - BCPLComment | C99 | C1X | Digraphs | GNUMode | HexFloat) + "ISO C 2011 with GNU extensions", + BCPLComment | C99 | C11 | Digraphs | GNUMode | HexFloat) // C++ modes LANGSTANDARD(cxx98, "c++98", diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h new file mode 100644 index 0000000..225efe6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h @@ -0,0 +1,61 @@ +//===--- LayoutOverrideSource.h --Override Record Layouts -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H +#define LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H + +#include "clang/AST/ExternalASTSource.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + /// \brief An external AST source that overrides the layout of + /// a specified set of record types. + /// + /// This class is used only for testing the ability of external AST sources + /// to override the layout of record types. Its input is the output format + /// of the command-line argument -fdump-record-layouts. + class LayoutOverrideSource : public ExternalASTSource { + /// \brief The layout of a given record. + struct Layout { + /// \brief The size of the record. + uint64_t Size; + + /// \brief The alignment of the record. + uint64_t Align; + + /// \brief The offsets of the fields, in source order. + llvm::SmallVector<uint64_t, 8> FieldOffsets; + }; + + /// \brief The set of layouts that will be overridden. + llvm::StringMap<Layout> Layouts; + + public: + /// \brief Create a new AST source that overrides the layout of some + /// set of record types. + /// + /// The file is the result of passing -fdump-record-layouts to a file. + explicit LayoutOverrideSource(llvm::StringRef Filename); + + /// \brief If this particular record type has an overridden layout, + /// return that layout. + virtual bool + layoutRecordType(const RecordDecl *Record, + uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); + + /// \brief Dump the overridden layouts. + void dump(); + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h new file mode 100644 index 0000000..f9554e4 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h @@ -0,0 +1,31 @@ +//===--- MigratorOptions.h - MigratorOptions Options ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains the structures necessary for a front-end to specify +// various migration analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS +#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS + +namespace clang { + +class MigratorOptions { +public: + unsigned NoNSAllocReallocError : 1; + unsigned NoFinalizeRemoval : 1; + MigratorOptions() { + NoNSAllocReallocError = 0; + NoFinalizeRemoval = 0; + } +}; + +} +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h index 4242f01..ffa7b4a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h @@ -15,7 +15,9 @@ #ifndef CLANG_FRONTEND_MULTIPLEXCONSUMER_H #define CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#include "clang/Basic/LLVM.h" #include "clang/Sema/SemaConsumer.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" #include <vector> @@ -28,15 +30,18 @@ class MultiplexASTDeserializationListener; class MultiplexConsumer : public SemaConsumer { public: // Takes ownership of the pointers in C. - MultiplexConsumer(const std::vector<ASTConsumer*>& C); + MultiplexConsumer(ArrayRef<ASTConsumer*> C); ~MultiplexConsumer(); // ASTConsumer virtual void Initialize(ASTContext &Context); - virtual void HandleTopLevelDecl(DeclGroupRef D); + virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); + virtual bool HandleTopLevelDecl(DeclGroupRef D); virtual void HandleInterestingDecl(DeclGroupRef D); virtual void HandleTranslationUnit(ASTContext &Ctx); virtual void HandleTagDeclDefinition(TagDecl *D); + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D); + virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); virtual void CompleteTentativeDefinition(VarDecl *D); virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired); virtual ASTMutationListener *GetASTMutationListener(); @@ -50,8 +55,8 @@ public: static bool classof(const MultiplexConsumer *) { return true; } private: std::vector<ASTConsumer*> Consumers; // Owns these. - llvm::OwningPtr<MultiplexASTMutationListener> MutationListener; - llvm::OwningPtr<MultiplexASTDeserializationListener> DeserializationListener; + OwningPtr<MultiplexASTMutationListener> MutationListener; + OwningPtr<MultiplexASTDeserializationListener> DeserializationListener; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h index 0ee8cb3..d86a923 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ #define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include <cassert> #include <string> @@ -49,14 +50,10 @@ public: unsigned DetailedRecord : 1; /// Whether we should maintain a detailed /// record of all macro definitions and /// expansions. - - /// \brief Whether we should automatically translate #include or #import - /// operations into module imports when possible. - unsigned AutoModuleImport : 1; - - /// \brief Whether the detailed preprocessing record includes nested macro - /// expansions. - unsigned DetailedRecordIncludesNestedMacroExpansions : 1; + unsigned DetailedRecordConditionalDirectives : 1; /// Whether in the + /// preprocessing record we should also keep + /// track of locations of conditional directives + /// in non-system files. /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -72,6 +69,9 @@ public: /// precompiled header or AST file. bool DisableStatCache; + /// \brief When true, a PCH with compiler errors will not be rejected. + bool AllowPCHWithCompilerErrors; + /// \brief Dump declarations that are deserialized from PCH, for testing. bool DumpDeserializedPCHDecls; @@ -166,9 +166,9 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - AutoModuleImport(false), - DetailedRecordIncludesNestedMacroExpansions(true), + DetailedRecordConditionalDirectives(false), DisablePCHValidation(false), DisableStatCache(false), + AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), RemappedFilesKeepOriginalName(true), diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h new file mode 100644 index 0000000..aa0695f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -0,0 +1,62 @@ +//===--- SerializedDiagnosticPrinter.h - Serializer for diagnostics -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ +#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ + +#include "llvm/Bitcode/BitstreamWriter.h" + +namespace llvm { +class raw_ostream; +} + +namespace clang { +class DiagnosticConsumer; +class DiagnosticsEngine; +class DiagnosticOptions; + +namespace serialized_diags { + +enum BlockIDs { + /// \brief A top-level block which represents any meta data associated + /// with the diagostics, including versioning of the format. + BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// \brief The this block acts as a container for all the information + /// for a specific diagnostic. + BLOCK_DIAG +}; + +enum RecordIDs { + RECORD_VERSION = 1, + RECORD_DIAG, + RECORD_SOURCE_RANGE, + RECORD_DIAG_FLAG, + RECORD_CATEGORY, + RECORD_FILENAME, + RECORD_FIXIT, + RECORD_FIRST = RECORD_VERSION, + RECORD_LAST = RECORD_FIXIT +}; + +/// \brief Returns a DiagnosticConsumer that serializes diagnostics to +/// a bitcode file. +/// +/// The created DiagnosticConsumer is designed for quick and lightweight +/// transfer of of diagnostics to the enclosing build system (e.g., an IDE). +/// This allows wrapper tools for Clang to get diagnostics from Clang +/// (via libclang) without needing to parse Clang's command line output. +/// +DiagnosticConsumer *create(llvm::raw_ostream *OS, + const DiagnosticOptions &diags); + +} // end serialized_diags namespace +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h new file mode 100644 index 0000000..519d3b6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h @@ -0,0 +1,120 @@ +//===--- TextDiagnostic.h - Text Diagnostic Pretty-Printing -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a utility class that provides support for textual pretty-printing of +// diagnostics. It is used to implement the different code paths which require +// such functionality in a consistent way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_H_ +#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_H_ + +#include "clang/Frontend/DiagnosticRenderer.h" + +namespace clang { + +/// \brief Class to encapsulate the logic for formatting and printing a textual +/// diagnostic message. +/// +/// This class provides an interface for building and emitting a textual +/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt +/// Hints, and code snippets. In the presence of macros this involves +/// a recursive process, synthesizing notes for each macro expansion. +/// +/// The purpose of this class is to isolate the implementation of printing +/// beautiful text diagnostics from any particular interfaces. The Clang +/// DiagnosticClient is implemented through this class as is diagnostic +/// printing coming out of libclang. +class TextDiagnostic : public DiagnosticRenderer { + raw_ostream &OS; + +public: + TextDiagnostic(raw_ostream &OS, + const SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticOptions &DiagOpts); + + virtual ~TextDiagnostic(); + + /// \brief Print the diagonstic level to a raw_ostream. + /// + /// This is a static helper that handles colorizing the level and formatting + /// it into an arbitrary output stream. This is used internally by the + /// TextDiagnostic emission code, but it can also be used directly by + /// consumers that don't have a source manager or other state that the full + /// TextDiagnostic logic requires. + static void printDiagnosticLevel(raw_ostream &OS, + DiagnosticsEngine::Level Level, + bool ShowColors); + + /// \brief Pretty-print a diagnostic message to a raw_ostream. + /// + /// This is a static helper to handle the line wrapping, colorizing, and + /// rendering of a diagnostic message to a particular ostream. It is + /// publically visible so that clients which do not have sufficient state to + /// build a complete TextDiagnostic object can still get consistent + /// formatting of their diagnostic messages. + /// + /// \param OS Where the message is printed + /// \param Level Used to colorizing the message + /// \param Message The text actually printed + /// \param CurrentColumn The starting column of the first line, accounting + /// for any prefix. + /// \param Columns The number of columns to use in line-wrapping, 0 disables + /// all line-wrapping. + /// \param ShowColors Enable colorizing of the message. + static void printDiagnosticMessage(raw_ostream &OS, + DiagnosticsEngine::Level Level, + StringRef Message, + unsigned CurrentColumn, unsigned Columns, + bool ShowColors); + +protected: + virtual void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<CharSourceRange> Ranges, + DiagOrStoredDiag D); + + virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges); + + virtual void emitCodeContext(SourceLocation Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints) { + emitSnippetAndCaret(Loc, Level, Ranges, Hints); + } + + virtual void emitBasicNote(StringRef Message); + + virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc); + +private: + void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints); + + void highlightRange(const CharSourceRange &R, + unsigned LineNo, FileID FID, + const std::string &SourceLine, + std::string &CaretLine); + std::string buildFixItInsertionLine(unsigned LineNo, + const char *LineStart, + const char *LineEnd, + ArrayRef<FixItHint> Hints); + void expandTabs(std::string &SourceLine, std::string &CaretLine); + void emitParseableFixits(ArrayRef<FixItHint> Hints); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h index 22fa18b..9b6ac24 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h @@ -16,25 +16,28 @@ #define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/OwningPtr.h" namespace clang { class DiagnosticOptions; class LangOptions; +class TextDiagnostic; class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; const LangOptions *LangOpts; const DiagnosticOptions *DiagOpts; + const SourceManager *SM; - SourceLocation LastWarningLoc; - FullSourceLoc LastLoc; - unsigned LastCaretDiagnosticWasNote : 1; - unsigned OwnsOutputStream : 1; + /// \brief Handle to the currently active text diagnostic emitter. + OwningPtr<TextDiagnostic> TextDiag; /// A string to prefix to error messages. std::string Prefix; + unsigned OwnsOutputStream : 1; + public: TextDiagnosticPrinter(raw_ostream &os, const DiagnosticOptions &diags, bool OwnsOutputStream = false); @@ -45,27 +48,10 @@ public: /// used. void setPrefix(std::string Value) { Prefix = Value; } - void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { - LangOpts = &LO; - } - - void EndSourceFile() { - LangOpts = 0; - } - - void PrintIncludeStack(DiagnosticsEngine::Level Level, SourceLocation Loc, - const SourceManager &SM); - - virtual void HandleDiagnostic(DiagnosticsEngine::Level Level, - const Diagnostic &Info); - + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP); + void EndSourceFile(); + void HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const; - -private: - void EmitDiagnosticLoc(DiagnosticsEngine::Level Level, - const Diagnostic &Info, - const SourceManager &SM, - PresumedLoc PLoc); }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h index 929beb0..6b1fc63 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h @@ -15,13 +15,11 @@ #define LLVM_CLANG_FRONTEND_UTILS_H #include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/Support/raw_ostream.h" -#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/StringRef.h" namespace llvm { +class raw_fd_ostream; class Triple; } @@ -46,11 +44,6 @@ class Stmt; class TargetInfo; class FrontendOptions; -/// Normalize \arg File for use in a user defined #include directive (in the -/// predefines buffer). -std::string NormalizeDashIncludePath(StringRef File, - FileManager &FileMgr); - /// Apply the header search options to get given HeaderSearch object. void ApplyHeaderSearchOptions(HeaderSearch &HS, const HeaderSearchOptions &HSOpts, @@ -66,7 +59,8 @@ void InitializePreprocessor(Preprocessor &PP, /// ProcessWarningOptions - Initialize the diagnostic client and process the /// warning options specified on the command line. -void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts); +void ProcessWarningOptions(DiagnosticsEngine &Diags, + const DiagnosticOptions &Opts); /// DoPrintPreprocessedInput - Implement -E mode. void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, @@ -77,6 +71,11 @@ void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, void AttachDependencyFileGen(Preprocessor &PP, const DependencyOutputOptions &Opts); +/// AttachDependencyGraphGen - Create a dependency graph generator, and attach +/// it to the given preprocessor. + void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, + StringRef SysRoot); + /// AttachHeaderIncludeGen - Create a header include list generator, and attach /// it to the given preprocessor. /// @@ -101,8 +100,8 @@ void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); /// argument vector. CompilerInvocation * createInvocationFromCommandLine(ArrayRef<const char *> Args, - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = - llvm::IntrusiveRefCntPtr<DiagnosticsEngine>()); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags = + IntrusiveRefCntPtr<DiagnosticsEngine>()); } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h index 28dc9de..2fc6ccc 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -67,7 +67,7 @@ public: DiagnosticsEngine &Diags; DiagnosticConsumer *PrimaryClient; bool OwnsPrimaryClient; - llvm::OwningPtr<TextDiagnosticBuffer> Buffer; + OwningPtr<TextDiagnosticBuffer> Buffer; Preprocessor *CurrentPreprocessor; private: diff --git a/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h index 7b66e7e..45097cc 100644 --- a/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h +++ b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h @@ -16,6 +16,7 @@ #include "clang/AST/TypeLoc.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" namespace clang { class Decl; @@ -42,7 +43,7 @@ public: struct NamedRef { NamedDecl *ND; SourceLocation Loc; - + NamedRef() : ND(0) { } NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { } }; @@ -95,14 +96,14 @@ public: bool isValid() const { return ParentDecl.getPointer() != 0; } bool isInvalid() const { return !isValid(); } - + NodeKind getKind() const { assert(isValid()); return (NodeKind)ParentDecl.getInt(); } - + Decl *getParentDecl() const { return ParentDecl.getPointer(); } - + Decl *AsDecl() const { assert(getKind() == N_Decl); return D; @@ -121,14 +122,16 @@ public: } Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } - Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; } + Stmt *dyn_AsStmt() const { + return isValid() && getKind() == N_Stmt ? Stm : 0; + } NamedRef dyn_AsNamedRef() const { return getKind() == N_Type ? AsNamedRef() : NamedRef(); } TypeLoc dyn_AsTypeLoc() const { return getKind() == N_Type ? AsTypeLoc() : TypeLoc(); } - + bool isDecl() const { return isValid() && getKind() == N_Decl; } bool isStmt() const { return isValid() && getKind() == N_Stmt; } bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; } @@ -144,7 +147,7 @@ public: return const_cast<ASTLocation*>(this)->getReferencedDecl(); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; void print(raw_ostream &OS) const; }; diff --git a/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Index/GlobalCallGraph.h index 38baf0f..7ba1cce 100644 --- a/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h +++ b/contrib/llvm/tools/clang/include/clang/Index/GlobalCallGraph.h @@ -1,4 +1,4 @@ -//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==// +//== GlobalCallGraph.h - Call graph building --------------------*- C++ -*--==// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH -#define LLVM_CLANG_ANALYSIS_CALLGRAPH +#ifndef LLVM_CLANG_INDEX_CALLGRAPH +#define LLVM_CLANG_INDEX_CALLGRAPH #include "clang/Index/ASTLocation.h" #include "clang/Index/Entity.h" @@ -23,15 +23,18 @@ #include <vector> #include <map> +using namespace clang; + namespace clang { +namespace idx { class CallGraphNode { - idx::Entity F; - typedef std::pair<idx::ASTLocation, CallGraphNode*> CallRecord; + Entity F; + typedef std::pair<ASTLocation, CallGraphNode*> CallRecord; std::vector<CallRecord> CalledFunctions; public: - CallGraphNode(idx::Entity f) : F(f) {} + CallGraphNode(Entity f) : F(f) {} typedef std::vector<CallRecord>::iterator iterator; typedef std::vector<CallRecord>::const_iterator const_iterator; @@ -41,7 +44,7 @@ public: const_iterator begin() const { return CalledFunctions.begin(); } const_iterator end() const { return CalledFunctions.end(); } - void addCallee(idx::ASTLocation L, CallGraphNode *Node) { + void addCallee(ASTLocation L, CallGraphNode *Node) { CalledFunctions.push_back(std::make_pair(L, Node)); } @@ -54,9 +57,9 @@ public: class CallGraph { /// Program manages all Entities. - idx::Program &Prog; + Program &Prog; - typedef std::map<idx::Entity, CallGraphNode *> FunctionMapTy; + typedef std::map<Entity, CallGraphNode *> FunctionMapTy; /// FunctionMap owns all CallGraphNodes. FunctionMapTy FunctionMap; @@ -71,7 +74,7 @@ class CallGraph { CallGraphNode *ExternalCallingNode; public: - CallGraph(idx::Program &P); + CallGraph(Program &P); ~CallGraph(); typedef FunctionMapTy::iterator iterator; @@ -88,7 +91,7 @@ public: void addTU(ASTContext &AST); - idx::Program &getProgram() { return Prog; } + Program &getProgram() { return Prog; } CallGraphNode *getOrInsertFunction(idx::Entity F); @@ -100,13 +103,13 @@ public: void ViewCallGraph() const; }; -} // end clang namespace +}} // end clang idx namespace namespace llvm { -template <> struct GraphTraits<clang::CallGraph> { - typedef clang::CallGraph GraphType; - typedef clang::CallGraphNode NodeType; +template <> struct GraphTraits<clang::idx::CallGraph> { + typedef clang::idx::CallGraph GraphType; + typedef clang::idx::CallGraphNode NodeType; typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy; typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h index f7da61b..95f0d27 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h @@ -22,7 +22,8 @@ class HeaderMap; class DirectoryEntry; class FileEntry; class HeaderSearch; - +class Module; + /// DirectoryLookup - This class represents one entry in the search list that /// specifies the search order for directories in #include directives. It /// represents either a directory, a framework, or a headermap. @@ -141,24 +142,26 @@ public: /// SearchPath at which the file was found. This only differs from the /// Filename for framework includes. /// - /// \param BuildingModule The name of the module we're currently building. - /// /// \param SuggestedModule If non-null, and the file found is semantically - /// part of a known module, this will be set to the name of the module that - /// could be imported instead of preprocessing/parsing the file found. + /// part of a known module, this will be set to the module that should + /// be imported instead of preprocessing/parsing the file found. + /// + /// \param InUserSpecifiedSystemHeader [out] If the file is found, set to true + /// if the file is located in a framework that has been user-specified to be + /// treated as a system framework. const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const; + Module **SuggestedModule, + bool &InUserSpecifiedSystemHeader) const; private: const FileEntry *DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const; + Module **SuggestedModule, + bool &InUserSpecifiedSystemHeader) const; }; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h index dbf7389..f172b5c 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h @@ -30,6 +30,9 @@ public: /// \brief Read the definition for the given macro. virtual void LoadMacroDefinition(IdentifierInfo *II) = 0; + + /// \brief Update an out-of-date identifier. + virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0; }; } diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h index 84d59f7..5128ce6 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h @@ -15,13 +15,16 @@ #define LLVM_CLANG_LEX_HEADERSEARCH_H #include "clang/Lex/DirectoryLookup.h" +#include "clang/Lex/ModuleMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" +#include "llvm/ADT/OwningPtr.h" #include <vector> namespace clang { - + +class DiagnosticsEngine; class ExternalIdentifierLookup; class FileEntry; class FileManager; @@ -117,7 +120,19 @@ public: /// HeaderSearch - This class encapsulates the information needed to find the /// file referenced by a #include or #include_next, (sub-)framework lookup, etc. class HeaderSearch { + /// This structure is used to record entries in our framework cache. + struct FrameworkCacheEntry { + /// The directory entry which should be used for the cached framework. + const DirectoryEntry *Directory; + + /// Whether this framework has been "user-specified" to be treated as if it + /// were a system framework (even if it was found outside a system framework + /// directory). + bool IsUserSpecifiedSystemFramework; + }; + FileManager &FileMgr; + DiagnosticsEngine &Diags; /// #include search path information. Requests for #include "x" search the /// directory of the #including file first, then each directory in SearchDirs /// consecutively. Requests for <x> search the current dir first, then each @@ -132,9 +147,6 @@ class HeaderSearch { /// \brief The path to the module cache. std::string ModuleCachePath; - /// \brief The name of the module we're building. - std::string BuildingModule; - /// FileInfo - This contains all of the preprocessor-specific data about files /// that are included. The vector is indexed by the FileEntry's UID. /// @@ -149,16 +161,27 @@ class HeaderSearch { llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator> LookupFileCache; - /// FrameworkMap - This is a collection mapping a framework or subframework /// name like "Carbon" to the Carbon.framework directory. - llvm::StringMap<const DirectoryEntry *, llvm::BumpPtrAllocator> - FrameworkMap; + llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap; + + /// IncludeAliases - maps include file names (including the quotes or + /// angle brackets) to other include file names. This is used to support the + /// include_alias pragma for Microsoft compatibility. + typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator> + IncludeAliasMap; + OwningPtr<IncludeAliasMap> IncludeAliases; /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing /// headermaps. This vector owns the headermap. std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; + /// \brief The mapping between modules and headers. + ModuleMap ModMap; + + /// \brief Describes whether a given directory has a module map in it. + llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; + /// \brief Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames; @@ -179,8 +202,12 @@ class HeaderSearch { explicit HeaderSearch(); explicit HeaderSearch(const HeaderSearch&); void operator=(const HeaderSearch&); + + friend class DirectoryLookup; + public: - HeaderSearch(FileManager &FM); + HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, + const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); FileManager &getFileMgr() const { return FileMgr; } @@ -199,13 +226,51 @@ public: //LookupFileCache.clear(); } - /// \brief Set the path to the module cache and the name of the module - /// we're building - void configureModules(StringRef CachePath, StringRef BuildingModule) { + /// AddSearchPath - Add an additional search path. + void AddSearchPath(const DirectoryLookup &dir, bool isAngled) { + unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; + SearchDirs.insert(SearchDirs.begin() + idx, dir); + if (!isAngled) + AngledDirIdx++; + SystemDirIdx++; + } + + /// HasIncludeAliasMap - Checks whether the map exists or not + bool HasIncludeAliasMap() const { + return IncludeAliases; + } + + /// AddIncludeAlias - Map the source include name to the dest include name. + /// The Source should include the angle brackets or quotes, the dest + /// should not. This allows for distinction between <> and "" headers. + void AddIncludeAlias(StringRef Source, StringRef Dest) { + if (!IncludeAliases) + IncludeAliases.reset(new IncludeAliasMap); + (*IncludeAliases)[Source] = Dest; + } + + /// MapHeaderToIncludeAlias - Maps one header file name to a different header + /// file name, for use with the include_alias pragma. Note that the source + /// file name should include the angle brackets or quotes. Returns StringRef + /// as null if the header cannot be mapped. + StringRef MapHeaderToIncludeAlias(StringRef Source) { + assert(IncludeAliases && "Trying to map headers when there's no map"); + + // Do any filename replacements before anything else + IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source); + if (Iter != IncludeAliases->end()) + return Iter->second; + return StringRef(); + } + + /// \brief Set the path to the module cache. + void setModuleCachePath(StringRef CachePath) { ModuleCachePath = CachePath; - this->BuildingModule = BuildingModule; } + /// \brief Retrieve the path to the module cache. + StringRef getModuleCachePath() const { return ModuleCachePath; } + /// ClearFileInfo - Forget everything we know about headers so far. void ClearFileInfo() { FileInfo.clear(); @@ -224,6 +289,10 @@ public: ExternalSource = ES; } + /// \brief Set the target information for the header search, if not + /// already known. + void setTarget(const TargetInfo &Target); + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. /// @@ -247,15 +316,16 @@ public: /// Filename for framework includes. /// /// \param SuggestedModule If non-null, and the file found is semantically - /// part of a known module, this will be set to the name of the module that - /// could be imported instead of preprocessing/parsing the file found. + /// part of a known module, this will be set to the module that should + /// be imported instead of preprocessing/parsing the file found. const FileEntry *LookupFile(StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule); + Module **SuggestedModule, + bool SkipCache = false); /// LookupSubframeworkHeader - Look up a subframework for the specified /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from @@ -271,7 +341,7 @@ public: /// LookupFrameworkCache - Look up the specified framework name in our /// framework cache, returning the DirectoryEntry it is in if we know, /// otherwise, return null. - const DirectoryEntry *&LookupFrameworkCache(StringRef FWName) { + FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) { return FrameworkMap.GetOrCreateValue(FWName).getValue(); } @@ -326,33 +396,96 @@ public: /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. const HeaderMap *CreateHeaderMap(const FileEntry *FE); - /// \brief Search in the module cache path for a module with the given - /// name. + /// \brief Retrieve the name of the module file that should be used to + /// load the given module. /// - /// \param If non-NULL, will be set to the module file name we expected to - /// find (regardless of whether it was actually found or not). + /// \param Module The module whose module file name will be returned. /// - /// \param UmbrellaHeader If non-NULL, and no module was found in the module - /// cache, this routine will search in the framework paths to determine - /// whether a module can be built from an umbrella header. If so, the pointee - /// will be set to the path of the umbrella header. + /// \returns The name of the module file that corresponds to this module, + /// or an empty string if this module does not correspond to any module file. + std::string getModuleFileName(Module *Module); + + /// \brief Retrieve the name of the module file that should be used to + /// load a module with the given name. + /// + /// \param Module The module whose module file name will be returned. + /// + /// \returns The name of the module file that corresponds to this module, + /// or an empty string if this module does not correspond to any module file. + std::string getModuleFileName(StringRef ModuleName); + + /// \brief Lookup a module Search for a module with the given name. /// - /// \returns A file describing the named module, if available, or NULL to - /// indicate that the module could not be found. - const FileEntry *lookupModule(StringRef ModuleName, - std::string *ModuleFileName = 0, - std::string *UmbrellaHeader = 0); + /// \param ModuleName The name of the module we're looking for. + /// + /// \param AllowSearch Whether we are allowed to search in the various + /// search directories to produce a module definition. If not, this lookup + /// will only return an already-known module. + /// + /// \returns The module with the given name. + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } - typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator; - header_file_iterator header_file_begin() const { return FileInfo.begin(); } - header_file_iterator header_file_end() const { return FileInfo.end(); } + /// \brief Determine whether there is a module map that may map the header + /// with the given file name to a (sub)module. + /// + /// \param Filename The name of the file. + /// + /// \param Root The "root" directory, at which we should stop looking for + /// module maps. + bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root); + + /// \brief Retrieve the module that corresponds to the given file, if any. + /// + /// \param File The header that we wish to map to a module. + Module *findModuleForHeader(const FileEntry *File); + + /// \brief Read the contents of the given module map file. + /// + /// \param File The module map file. + /// + /// \param OnlyModule If non-NULL, this will receive the + /// + /// \returns true if an error occurred, false otherwise. + bool loadModuleMapFile(const FileEntry *File); + + /// \brief Collect the set of all known, top-level modules. + /// + /// \param Modules Will be filled with the set of known, top-level modules. + void collectAllModules(llvm::SmallVectorImpl<Module *> &Modules); + +private: + /// \brief Retrieve a module with the given name, which may be part of the + /// given framework. + /// + /// \param Name The name of the module to retrieve. + /// + /// \param Dir The framework directory (e.g., ModuleName.framework). + /// + /// \param IsSystem Whether the framework directory is part of the system + /// frameworks. + /// + /// \returns The module, if found; otherwise, null. + Module *loadFrameworkModule(StringRef Name, + const DirectoryEntry *Dir, + bool IsSystem); + +public: + /// \brief Retrieve the module map. + ModuleMap &getModuleMap() { return ModMap; } + unsigned header_file_size() const { return FileInfo.size(); } // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); + /// getFileInfo - Return the HeaderFileInfo structure for the specified + /// FileEntry. + const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { + return const_cast<HeaderSearch*>(this)->getFileInfo(FE); + } + // Used by external tools typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } @@ -385,7 +518,39 @@ public: size_t getTotalMemory() const; + static std::string NormalizeDashIncludePath(StringRef File, + FileManager &FileMgr); + private: + /// \brief Describes what happened when we tried to load a module map file. + enum LoadModuleMapResult { + /// \brief The module map file had already been loaded. + LMM_AlreadyLoaded, + /// \brief The module map file was loaded by this invocation. + LMM_NewlyLoaded, + /// \brief There is was directory with the given name. + LMM_NoDirectory, + /// \brief There was either no module map file or the module map file was + /// invalid. + LMM_InvalidModuleMap + }; + + /// \brief Try to load the module map file in the given directory. + /// + /// \param DirName The name of the directory where we will look for a module + /// map file. + /// + /// \returns The result of attempting to load the module map file from the + /// named directory. + LoadModuleMapResult loadModuleMapFile(StringRef DirName); + + /// \brief Try to load the module map file in the given directory. + /// + /// \param Dir The directory where we will look for a module map file. + /// + /// \returns The result of attempting to load the module map file from the + /// named directory. + LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir); /// getFileInfo - Return the HeaderFileInfo structure for the specified /// FileEntry. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h index f454e23..41b9396 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define LEXSTART #include "clang/Basic/DiagnosticLexKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h index e01427f..04bcead 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h @@ -44,12 +44,14 @@ enum ConflictMarkerKind { /// or buffering/seeking of tokens, only forward lexing is supported. It relies /// on the specified Preprocessor object to handle preprocessor directives, etc. class Lexer : public PreprocessorLexer { + virtual void anchor(); + //===--------------------------------------------------------------------===// // Constant configuration values for this lexer. const char *BufferStart; // Start of the buffer. const char *BufferEnd; // End of the buffer. SourceLocation FileLoc; // Location for start of file. - LangOptions Features; // Features enabled by this language (cache). + LangOptions LangOpts; // LangOpts enabled by this language (cache). bool Is_PragmaLexer; // True if lexer for _Pragma handling. //===--------------------------------------------------------------------===// @@ -97,14 +99,14 @@ public: /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexRawToken'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. - Lexer(SourceLocation FileLoc, const LangOptions &Features, + Lexer(SourceLocation FileLoc, const LangOptions &LangOpts, const char *BufStart, const char *BufPtr, const char *BufEnd); /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexRawToken'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, - const SourceManager &SM, const LangOptions &Features); + const SourceManager &SM, const LangOptions &LangOpts); /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for /// _Pragma expansion. This has a variety of magic semantics that this method @@ -115,9 +117,9 @@ public: unsigned TokLen, Preprocessor &PP); - /// getFeatures - Return the language features currently enabled. NOTE: this - /// lexer modifies features as a file is parsed! - const LangOptions &getFeatures() const { return Features; } + /// getLangOpts - Return the language features currently enabled. + /// NOTE: this lexer modifies features as a file is parsed! + const LangOptions &getLangOpts() const { return LangOpts; } /// getFileLoc - Return the File Location for the file we are lexing out of. /// The physical location encodes the location where the characters come from, @@ -238,7 +240,7 @@ public: /// if an internal buffer is returned. static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *Invalid = 0); /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a @@ -248,7 +250,7 @@ public: /// UCNs, etc. static std::string getSpelling(const Token &Tok, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *Invalid = 0); /// getSpelling - This method is used to get the spelling of the @@ -262,7 +264,7 @@ public: static StringRef getSpelling(SourceLocation loc, SmallVectorImpl<char> &buffer, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *invalid = 0); /// MeasureTokenLength - Relex the token at the specified location and return @@ -288,7 +290,7 @@ public: static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Character, const SourceManager &SM, - const LangOptions &Features); + const LangOptions &LangOpts); /// \brief Computes the source location just past the end of the /// token at this source location. @@ -307,19 +309,52 @@ public: /// a source location pointing to the last character in the token, etc. static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, - const LangOptions &Features); + const LangOptions &LangOpts); /// \brief Returns true if the given MacroID location points at the first /// token of the macro expansion. + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// begin location of the macro. static bool isAtStartOfMacroExpansion(SourceLocation loc, - const SourceManager &SM, - const LangOptions &LangOpts); + const SourceManager &SM, + const LangOptions &LangOpts, + SourceLocation *MacroBegin = 0); /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// end location of the macro. static bool isAtEndOfMacroExpansion(SourceLocation loc, - const SourceManager &SM, - const LangOptions &LangOpts); + const SourceManager &SM, + const LangOptions &LangOpts, + SourceLocation *MacroEnd = 0); + + /// \brief Accepts a range and returns a character range with file locations. + /// + /// Returns a null range if a part of the range resides inside a macro + /// expansion or the range does not reside on the same FileID. + static CharSourceRange makeFileCharRange(CharSourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts); + + /// \brief Returns a string for the source that the range encompasses. + static StringRef getSourceText(CharSourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts, + bool *Invalid = 0); + + /// \brief Retrieve the name of the immediate macro expansion. + /// + /// This routine starts from a source location, and finds the name of the macro + /// responsible for its immediate expansion. It looks through any intervening + /// macro argument expansions to compute this. It returns a StringRef which + /// refers to the SourceManager-owned buffer of the source where that macro + /// name is spelled. Thus, the result shouldn't out-live that SourceManager. + static StringRef getImmediateMacroName(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); /// \brief Compute the preamble of the given file. /// @@ -337,7 +372,7 @@ public: /// of the file begins along with a boolean value indicating whether /// the preamble ends at the beginning of a new line. static std::pair<unsigned, bool> - ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &Features, + ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0); //===--------------------------------------------------------------------===// @@ -451,7 +486,7 @@ public: /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever /// emit a warning. static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &Features) { + const LangOptions &LangOpts) { // If this is not a trigraph and not a UCN or escaped newline, return // quickly. if (isObviouslySimpleCharacter(Ptr[0])) { @@ -460,7 +495,7 @@ public: } Size = 0; - return getCharAndSizeSlowNoWarn(Ptr, Size, Features); + return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); } /// getEscapedNewLineSize - Return the size of the specified escaped newline, @@ -489,12 +524,14 @@ private: /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a /// diagnostic. static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &Features); + const LangOptions &LangOpts); //===--------------------------------------------------------------------===// // Other lexer functions. void SkipBytes(unsigned Bytes, bool StartOfLine); + + const char *LexUDSuffix(Token &Result, const char *CurPtr); // Helper functions to lex the remainder of a token of the specific type. void LexIdentifier (Token &Result, const char *CurPtr); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h index b33092c..7e7f82f 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h @@ -45,7 +45,7 @@ class NumericLiteralParser { unsigned radix; - bool saw_exponent, saw_period; + bool saw_exponent, saw_period, saw_ud_suffix; public: NumericLiteralParser(const char *begin, const char *end, @@ -64,8 +64,17 @@ public: bool isFloatingLiteral() const { return saw_period || saw_exponent; } - bool hasSuffix() const { - return SuffixBegin != ThisTokEnd; + + bool hasUDSuffix() const { + return saw_ud_suffix; + } + StringRef getUDSuffix() const { + assert(saw_ud_suffix); + return StringRef(SuffixBegin, ThisTokEnd - SuffixBegin); + } + unsigned getUDSuffixOffset() const { + assert(saw_ud_suffix); + return SuffixBegin - ThisTokBegin; } unsigned getRadix() const { return radix; } @@ -128,6 +137,8 @@ class CharLiteralParser { tok::TokenKind Kind; bool IsMultiChar; bool HadError; + SmallString<32> UDSuffixBuf; + unsigned UDSuffixOffset; public: CharLiteralParser(const char *begin, const char *end, SourceLocation Loc, Preprocessor &PP, @@ -140,6 +151,11 @@ public: bool isUTF32() const { return Kind == tok::utf32_char_constant; } bool isMultiChar() const { return IsMultiChar; } uint64_t getValue() const { return Value; } + StringRef getUDSuffix() const { return UDSuffixBuf; } + unsigned getUDSuffixOffset() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixOffset; + } }; /// StringLiteralParser - This decodes string escape characters and performs @@ -155,8 +171,11 @@ class StringLiteralParser { unsigned SizeBound; unsigned CharByteWidth; tok::TokenKind Kind; - llvm::SmallString<512> ResultBuf; + SmallString<512> ResultBuf; char *ResultPtr; // cursor + SmallString<32> UDSuffixBuf; + unsigned UDSuffixToken; + unsigned UDSuffixOffset; public: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, Preprocessor &PP, bool Complain = true); @@ -189,15 +208,30 @@ public: /// checking of the string literal and emit errors and warnings. unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const; - bool isAscii() { return Kind == tok::string_literal; } - bool isWide() { return Kind == tok::wide_string_literal; } - bool isUTF8() { return Kind == tok::utf8_string_literal; } - bool isUTF16() { return Kind == tok::utf16_string_literal; } - bool isUTF32() { return Kind == tok::utf32_string_literal; } + bool isAscii() const { return Kind == tok::string_literal; } + bool isWide() const { return Kind == tok::wide_string_literal; } + bool isUTF8() const { return Kind == tok::utf8_string_literal; } + bool isUTF16() const { return Kind == tok::utf16_string_literal; } + bool isUTF32() const { return Kind == tok::utf32_string_literal; } + bool isPascal() const { return Pascal; } + + StringRef getUDSuffix() const { return UDSuffixBuf; } + + /// Get the index of a token containing a ud-suffix. + unsigned getUDSuffixToken() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixToken; + } + /// Get the spelling offset of the first byte of the ud-suffix. + unsigned getUDSuffixOffset() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixOffset; + } private: void init(const Token *StringToks, unsigned NumStringToks); - void CopyStringFragment(StringRef Fragment); + bool CopyStringFragment(StringRef Fragment); + bool DiagnoseBadString(const Token& Tok); }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h index b381e0f..8775d39 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h @@ -39,10 +39,11 @@ class MacroInfo { IdentifierInfo **ArgumentList; unsigned NumArguments; - /// \brief The location at which this macro was exported from its module. + /// \brief The location at which this macro was either explicitly exported + /// from its module or marked as private. /// - /// If invalid, this macro has not been explicitly exported. - SourceLocation ExportLocation; + /// If invalid, this macro has not been explicitly given any visibility. + SourceLocation VisibilityLocation; /// ReplacementTokens - This is the list of tokens that the macro is defined /// to. @@ -97,6 +98,9 @@ private: /// \brief Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; + /// \brief Whether the macro has public (when described in a module). + bool IsPublic : 1; + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } @@ -279,17 +283,18 @@ public: } /// \brief Set the export location for this macro. - void setExportLocation(SourceLocation ExportLoc) { - ExportLocation = ExportLoc; + void setVisibility(bool Public, SourceLocation Loc) { + VisibilityLocation = Loc; + IsPublic = Public; } - /// \brief Determine whether this macro was explicitly exported from its + /// \brief Determine whether this macro is part of the public API of its /// module. - bool isExported() const { return ExportLocation.isValid(); } + bool isPublic() const { return IsPublic; } - /// \brief Determine the location where this macro was explicitly exported - /// from its module. - SourceLocation getExportLocation() { return ExportLocation; } + /// \brief Determine the location where this macro was explicitly made + /// public or private within its module. + SourceLocation getVisibilityLocation() { return VisibilityLocation; } private: unsigned getDefinitionLengthSlow(SourceManager &SM) const; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h index 72ec0e3..36d03c0 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h @@ -14,15 +14,18 @@ #ifndef LLVM_CLANG_LEX_MODULE_LOADER_H #define LLVM_CLANG_LEX_MODULE_LOADER_H +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" namespace clang { class IdentifierInfo; -/// \brief An opaque key that is used to describe the module and can be -/// interpreted by the module loader itself. -typedef void *ModuleKey; +/// \brief A sequence of identifier/location pairs used to describe a particular +/// module or submodule, e.g., std.vector. +typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > + ModuleIdPath; /// \brief Abstract interface for a module loader. /// @@ -39,15 +42,22 @@ public: /// parameters. /// /// \param ImportLoc The location of the 'import' keyword. - /// \param ModuleName The name of the module to be loaded. - /// \param ModuleNameLoc The location of the module name. /// - /// \returns If successful, a non-NULL module key describing this module. - /// Otherwise, returns NULL to indicate that the module could not be - /// loaded. - virtual ModuleKey loadModule(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc) = 0; + /// \param Path The identifiers (and their locations) of the module + /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Visibility The visibility provided for the names in the loaded + /// module. + /// + /// \param IsInclusionDirective Indicates that this module is being loaded + /// implicitly, due to the presence of an inclusion directive. Otherwise, + /// it is being loaded due to an import declaration. + /// + /// \returns If successful, returns the loaded module. Otherwise, returns + /// NULL to indicate that the module could not be loaded. + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; }; } diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h new file mode 100644 index 0000000..4ebb1d4 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h @@ -0,0 +1,237 @@ +//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ModuleMap interface, which describes the layout of a +// module as it relates to headers. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_LEX_MODULEMAP_H +#define LLVM_CLANG_LEX_MODULEMAP_H + +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include <string> + +namespace clang { + +class DirectoryEntry; +class FileEntry; +class FileManager; +class DiagnosticConsumer; +class DiagnosticsEngine; +class ModuleMapParser; + +class ModuleMap { + SourceManager *SourceMgr; + IntrusiveRefCntPtr<DiagnosticsEngine> Diags; + const LangOptions &LangOpts; + const TargetInfo *Target; + + /// \brief The directory used for Clang-supplied, builtin include headers, + /// such as "stdint.h". + const DirectoryEntry *BuiltinIncludeDir; + + /// \brief Language options used to parse the module map itself. + /// + /// These are always simple C language options. + LangOptions MMapLangOpts; + + /// \brief The top-level modules that are known. + llvm::StringMap<Module *> Modules; + + /// \brief Mapping from each header to the module that owns the contents of the + /// that header. + llvm::DenseMap<const FileEntry *, Module *> Headers; + + /// \brief Mapping from directories with umbrella headers to the module + /// that is generated from the umbrella header. + /// + /// This mapping is used to map headers that haven't explicitly been named + /// in the module map over to the module that includes them via its umbrella + /// header. + llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; + + friend class ModuleMapParser; + + /// \brief Resolve the given export declaration into an actual export + /// declaration. + /// + /// \param Mod The module in which we're resolving the export declaration. + /// + /// \param Unresolved The export declaration to resolve. + /// + /// \param Complain Whether this routine should complain about unresolvable + /// exports. + /// + /// \returns The resolved export declaration, which will have a NULL pointer + /// if the export could not be resolved. + Module::ExportDecl + resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, + bool Complain); + +public: + /// \brief Construct a new module map. + /// + /// \param FileMgr The file manager used to find module files and headers. + /// This file manager should be shared with the header-search mechanism, since + /// they will refer to the same headers. + /// + /// \param DC A diagnostic consumer that will be cloned for use in generating + /// diagnostics. + /// + /// \param LangOpts Language options for this translation unit. + /// + /// \param Target The target for this translation unit. + ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, + const LangOptions &LangOpts, const TargetInfo *Target); + + /// \brief Destroy the module map. + /// + ~ModuleMap(); + + /// \brief Set the target information. + void setTarget(const TargetInfo &Target); + + /// \brief Set the directory that contains Clang-supplied include + /// files, such as our stdarg.h or tgmath.h. + void setBuiltinIncludeDir(const DirectoryEntry *Dir) { + BuiltinIncludeDir = Dir; + } + + /// \brief Retrieve the module that owns the given header file, if any. + /// + /// \param File The header file that is likely to be included. + /// + /// \returns The module that owns the given header file, or null to indicate + /// that no module owns this header file. + Module *findModuleForHeader(const FileEntry *File); + + /// \brief Determine whether the given header is part of a module + /// marked 'unavailable'. + bool isHeaderInUnavailableModule(const FileEntry *Header); + + /// \brief Retrieve a module with the given name. + /// + /// \param The name of the module to look up. + /// + /// \returns The named module, if known; otherwise, returns null. + Module *findModule(StringRef Name); + + /// \brief Retrieve a module with the given name using lexical name lookup, + /// starting at the given context. + /// + /// \param The name of the module to look up. + /// + /// \param Context The module context, from which we will perform lexical + /// name lookup. + /// + /// \returns The named module, if known; otherwise, returns null. + Module *lookupModuleUnqualified(StringRef Name, Module *Context); + + /// \brief Retrieve a module with the given name within the given context, + /// using direct (qualified) name lookup. + /// + /// \param The name of the module to look up. + /// + /// \param Context The module for which we will look for a submodule. If + /// null, we will look for a top-level module. + /// + /// \returns The named submodule, if known; otherwose, returns null. + Module *lookupModuleQualified(StringRef Name, Module *Context); + + /// \brief Find a new module or submodule, or create it if it does not already + /// exist. + /// + /// \param Name The name of the module to find or create. + /// + /// \param Parent The module that will act as the parent of this submodule, + /// or NULL to indicate that this is a top-level module. + /// + /// \param IsFramework Whether this is a framework module. + /// + /// \param IsExplicit Whether this is an explicit submodule. + /// + /// \returns The found or newly-created module, along with a boolean value + /// that will be true if the module is newly-created. + std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, + bool IsFramework, + bool IsExplicit); + + /// \brief Infer the contents of a framework module map from the given + /// framework directory. + Module *inferFrameworkModule(StringRef ModuleName, + const DirectoryEntry *FrameworkDir, + bool IsSystem, Module *Parent); + + /// \brief Retrieve the module map file containing the definition of the given + /// module. + /// + /// \param Module The module whose module map file will be returned, if known. + /// + /// \returns The file entry for the module map file containing the given + /// module, or NULL if the module definition was inferred. + const FileEntry *getContainingModuleMapFile(Module *Module); + + /// \brief Resolve all of the unresolved exports in the given module. + /// + /// \param Mod The module whose exports should be resolved. + /// + /// \param Complain Whether to emit diagnostics for failures. + /// + /// \returns true if any errors were encountered while resolving exports, + /// false otherwise. + bool resolveExports(Module *Mod, bool Complain); + + /// \brief Infers the (sub)module based on the given source location and + /// source manager. + /// + /// \param Loc The location within the source that we are querying, along + /// with its source manager. + /// + /// \returns The module that owns this source location, or null if no + /// module owns this source location. + Module *inferModuleFromLocation(FullSourceLoc Loc); + + /// \brief Sets the umbrella header of the given module to the given + /// header. + void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader); + + /// \brief Sets the umbrella directory of the given module to the given + /// directory. + void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir); + + /// \brief Adds this header to the given module. + void addHeader(Module *Mod, const FileEntry *Header); + + /// \brief Parse the given module map file, and record any modules we + /// encounter. + /// + /// \param File The file to be parsed. + /// + /// \returns true if an error occurred, false otherwise. + bool parseModuleMapFile(const FileEntry *File); + + /// \brief Dump the contents of the module map, for debugging purposes. + void dump(); + + typedef llvm::StringMap<Module *>::const_iterator module_iterator; + module_iterator module_begin() const { return Modules.begin(); } + module_iterator module_end() const { return Modules.end(); } +}; + +} +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h index 1fc1a05..33558c8 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h @@ -58,6 +58,23 @@ public: SrcMgr::CharacteristicKind FileType) { } + /// FileNotFound - This callback is invoked whenever an inclusion directive + /// results in a file-not-found error. + /// + /// \param FileName The name of the file being included, as written in the + /// source code. + /// + /// \param RecoveryPath If this client indicates that it can recover from + /// this missing file, the client should set this as an additional header + /// search patch. + /// + /// \returns true to indicate that the preprocessor should attempt to recover + /// by adding \p RecoveryPath as a header search path. + virtual bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) { + return false; + } + /// \brief This callback is invoked whenever an inclusion directive of /// any kind (\c #include, \c #import, etc.) has been processed, regardless /// of whether the inclusion will actually result in an inclusion. @@ -173,40 +190,49 @@ public: } /// If -- This hook is called whenever an #if is seen. - /// \param Range The SourceRange of the expression being tested. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. // FIXME: better to pass in a list (or tree!) of Tokens. - virtual void If(SourceRange Range) { + virtual void If(SourceLocation Loc, SourceRange ConditionRange) { } /// Elif -- This hook is called whenever an #elif is seen. - /// \param Range The SourceRange of the expression being tested. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. // FIXME: better to pass in a list (or tree!) of Tokens. - virtual void Elif(SourceRange Range) { + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) { } /// Ifdef -- This hook is called whenever an #ifdef is seen. - /// \param Loc The location of the token being tested. + /// \param Loc the source location of the directive. /// \param II Information on the token being tested. - virtual void Ifdef(const Token &MacroNameTok) { + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { } /// Ifndef -- This hook is called whenever an #ifndef is seen. - /// \param Loc The location of the token being tested. + /// \param Loc the source location of the directive. /// \param II Information on the token being tested. - virtual void Ifndef(const Token &MacroNameTok) { + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { } /// Else -- This hook is called whenever an #else is seen. - virtual void Else() { + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { } /// Endif -- This hook is called whenever an #endif is seen. - virtual void Endif() { + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { } }; /// PPChainedCallbacks - Simple wrapper class for chaining callbacks. class PPChainedCallbacks : public PPCallbacks { + virtual void anchor(); PPCallbacks *First, *Second; public: @@ -231,6 +257,12 @@ public: Second->FileSkipped(ParentFile, FilenameTok, FileType); } + virtual bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) { + return First->FileNotFound(FileName, RecoveryPath) || + Second->FileNotFound(FileName, RecoveryPath); + } + virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -311,39 +343,40 @@ public: } /// If -- This hook is called whenever an #if is seen. - virtual void If(SourceRange Range) { - First->If(Range); - Second->If(Range); + virtual void If(SourceLocation Loc, SourceRange ConditionRange) { + First->If(Loc, ConditionRange); + Second->If(Loc, ConditionRange); } /// Elif -- This hook is called whenever an #if is seen. - virtual void Elif(SourceRange Range) { - First->Elif(Range); - Second->Elif(Range); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) { + First->Elif(Loc, ConditionRange, IfLoc); + Second->Elif(Loc, ConditionRange, IfLoc); } /// Ifdef -- This hook is called whenever an #ifdef is seen. - virtual void Ifdef(const Token &MacroNameTok) { - First->Ifdef(MacroNameTok); - Second->Ifdef(MacroNameTok); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { + First->Ifdef(Loc, MacroNameTok); + Second->Ifdef(Loc, MacroNameTok); } /// Ifndef -- This hook is called whenever an #ifndef is seen. - virtual void Ifndef(const Token &MacroNameTok) { - First->Ifndef(MacroNameTok); - Second->Ifndef(MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { + First->Ifndef(Loc, MacroNameTok); + Second->Ifndef(Loc, MacroNameTok); } /// Else -- This hook is called whenever an #else is seen. - virtual void Else() { - First->Else(); - Second->Else(); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { + First->Else(Loc, IfLoc); + Second->Else(Loc, IfLoc); } /// Endif -- This hook is called whenever an #endif is seen. - virtual void Endif() { - First->Endif(); - Second->Endif(); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { + First->Endif(Loc, IfLoc); + Second->Endif(Loc, IfLoc); } }; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h index 53da19e..45e3a5d 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h @@ -17,8 +17,11 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" #include <vector> namespace clang { @@ -85,7 +88,7 @@ namespace clang { /// \brief Retrieve the source range that covers this entire preprocessed /// entity. - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } /// \brief Returns true if there was a problem loading the preprocessed /// entity. @@ -269,6 +272,13 @@ namespace clang { /// preprocessed entities that \arg Range encompasses. virtual std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range) = 0; + + /// \brief Optionally returns true or false if the preallocated preprocessed + /// entity with index \arg Index came from file \arg FID. + virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { + return llvm::Optional<bool>(); + } }; /// \brief A record of the steps taken while preprocessing a source file, @@ -276,10 +286,6 @@ namespace clang { /// expanded, etc. class PreprocessingRecord : public PPCallbacks { SourceManager &SourceMgr; - - /// \brief Whether we should include nested macro expansions in - /// the preprocessing record. - bool IncludeNestedMacroExpansions; /// \brief Allocator used to store preprocessing objects. llvm::BumpPtrAllocator BumpAlloc; @@ -295,6 +301,44 @@ namespace clang { /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; + bool RecordCondDirectives; + unsigned CondDirectiveNextIdx; + SmallVector<unsigned, 6> CondDirectiveStack; + + class CondDirectiveLoc { + SourceLocation Loc; + unsigned Idx; + + public: + CondDirectiveLoc(SourceLocation Loc, unsigned Idx) : Loc(Loc), Idx(Idx) {} + + SourceLocation getLoc() const { return Loc; } + unsigned getIdx() const { return Idx; } + + class Comp { + SourceManager &SM; + public: + explicit Comp(SourceManager &SM) : SM(SM) {} + bool operator()(const CondDirectiveLoc &LHS, + const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); + } + bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); + } + bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); + } + }; + }; + + typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; + /// \brief The locations of conditional directives in source order. + CondDirectiveLocsTy CondDirectiveLocs; + + void addCondDirectiveLoc(CondDirectiveLoc DirLoc); + unsigned findCondDirectiveIdx(SourceLocation Loc) const; + /// \brief Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to @@ -345,7 +389,7 @@ namespace clang { public: /// \brief Construct a new preprocessing record. - PreprocessingRecord(SourceManager &SM, bool IncludeNestedMacroExpansions); + PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { @@ -386,7 +430,7 @@ namespace clang { iterator() : Self(0), Position(0) { } - iterator(PreprocessingRecord *Self, int Position) + iterator(PreprocessingRecord *Self, PPEntityID Position) : Self(Self), Position(Position) { } value_type operator*() const { @@ -471,6 +515,7 @@ namespace clang { X.Position -= D; return X; } + friend class PreprocessingRecord; }; friend class iterator; @@ -496,11 +541,41 @@ namespace clang { /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities /// that source range \arg R encompasses. + /// + /// \param R the range to look for preprocessed entities. + /// std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R); + /// \brief Returns true if the preprocessed entity that \arg PPEI iterator + /// points to is coming from the file \arg FID. + /// + /// Can be used to avoid implicit deserializations of preallocated + /// preprocessed entities if we only care about entities of a specific file + /// and not from files #included in the range given at + /// \see getPreprocessedEntitiesInRange. + bool isEntityInFileID(iterator PPEI, FileID FID); + /// \brief Add a new preprocessed entity to this record. - void addPreprocessedEntity(PreprocessedEntity *Entity); - + PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity); + + /// \brief Returns true if this PreprocessingRecord is keeping track of + /// conditional directives locations. + bool isRecordingConditionalDirectives() const { + return RecordCondDirectives; + } + + /// \brief Returns true if the given range intersects with a conditional + /// directive. if a #if/#endif block is fully contained within the range, + /// this function will return false. + bool rangeIntersectsConditionalDirective(SourceRange Range) const; + + /// \brief Returns true if the given locations are in different regions, + /// separated by conditional directive blocks. + bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, + SourceLocation RHS) const { + return findCondDirectiveIdx(LHS) != findCondDirectiveIdx(RHS); + } + /// \brief Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source); @@ -513,6 +588,7 @@ namespace clang { /// \c MacroInfo. MacroDefinition *findMacroDefinition(const MacroInfo *MI); + private: virtual void MacroExpands(const Token &Id, const MacroInfo* MI, SourceRange Range); virtual void MacroDefined(const Token &Id, const MacroInfo *MI); @@ -525,6 +601,23 @@ namespace clang { SourceLocation EndLoc, StringRef SearchPath, StringRef RelativePath); + virtual void If(SourceLocation Loc, SourceRange ConditionRange); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); + + /// \brief Cached result of the last \see getPreprocessedEntitiesInRange + /// query. + struct { + SourceRange Range; + std::pair<PPEntityID, PPEntityID> Result; + } CachedRangeQuery; + + std::pair<PPEntityID, PPEntityID> + getPreprocessedEntitiesInRangeSlow(SourceRange R); friend class ASTReader; friend class ASTWriter; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h index 8b77433..055008f 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -33,6 +33,10 @@ #include "llvm/Support/Allocator.h" #include <vector> +namespace llvm { + template<unsigned InternalLen> class SmallString; +} + namespace clang { class SourceManager; @@ -50,15 +54,15 @@ class CodeCompletionHandler; class DirectoryLookup; class PreprocessingRecord; class ModuleLoader; - + /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor : public llvm::RefCountedBase<Preprocessor> { +class Preprocessor : public RefCountedBase<Preprocessor> { DiagnosticsEngine *Diags; - LangOptions &Features; + LangOptions &LangOpts; const TargetInfo *Target; FileManager &FileMgr; SourceManager &SourceMgr; @@ -69,10 +73,10 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; - + /// PTH - An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. - llvm::OwningPtr<PTHManager> PTH; + OwningPtr<PTHManager> PTH; /// BP - A BumpPtrAllocator object used to quickly allocate and release /// objects internal to the Preprocessor. @@ -107,8 +111,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { bool KeepComments : 1; bool KeepMacroComments : 1; bool SuppressIncludeNotFoundError : 1; - bool AutoModuleImport : 1; - + // State that changes while the preprocessor runs: bool InMacroArgs : 1; // True if parsing fn macro invocation args. @@ -121,6 +124,9 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// \brief Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; + /// \brief True if we are pre-expanding macro arguments. + bool InMacroArgPreExpansion; + /// Identifiers - This is mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; @@ -145,9 +151,13 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// with this preprocessor. std::vector<CommentHandler *> CommentHandlers; + /// \brief True if we want to ignore EOF token and continue later on (thus + /// avoid tearing the Lexer and etc. down). + bool IncrementalProcessing; + /// \brief The code-completion handler. CodeCompletionHandler *CodeComplete; - + /// \brief The file that we're performing code-completion for, if any. const FileEntry *CodeCompletionFile; @@ -163,14 +173,22 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// for preprocessing. SourceLocation CodeCompletionFileLoc; - /// \brief The source location of the __import_module__ keyword we just + /// \brief The source location of the 'import' contextual keyword we just /// lexed, if any. SourceLocation ModuleImportLoc; + /// \brief The module import path that we're currently processing. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> + ModuleImportPath; + + /// \brief Whether the module import expectes an identifier next. Otherwise, + /// it expects a '.' or ';'. + bool ModuleImportExpectsIdentifier; + /// \brief The source location of the currently-active /// #pragma clang arc_cf_code_audited begin. SourceLocation PragmaARCCFCodeAuditedLoc; - + /// \brief True if we hit the code-completion point. bool CodeCompletionReached; @@ -179,22 +197,22 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// with a flag that indicates whether skipping this number of bytes will /// place the lexer at the start of a line. std::pair<unsigned, bool> SkipMainFilePreamble; - + /// CurLexer - This is the current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - llvm::OwningPtr<Lexer> CurLexer; + OwningPtr<Lexer> CurLexer; /// CurPTHLexer - This is the current top of stack that we're lexing from if /// not expanding from a macro and we are lexing from a PTH cache. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - llvm::OwningPtr<PTHLexer> CurPTHLexer; + OwningPtr<PTHLexer> CurPTHLexer; /// CurPPLexer - This is the current top of the stack what we're lexing from /// if not expanding a macro. This is an alias for either CurLexer or /// CurPTHLexer. PreprocessorLexer *CurPPLexer; - + /// CurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to /// implement #include_next and find directory-specific properties. @@ -202,13 +220,13 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// CurTokenLexer - This is the current macro we are expanding, if we are /// expanding a macro. One of CurLexer and CurTokenLexer must be null. - llvm::OwningPtr<TokenLexer> CurTokenLexer; + OwningPtr<TokenLexer> CurTokenLexer; /// \brief The kind of lexer we're currently working with. - enum CurLexerKind { - CLK_Lexer, - CLK_PTHLexer, - CLK_TokenLexer, + enum CurLexerKind { + CLK_Lexer, + CLK_PTHLexer, + CLK_TokenLexer, CLK_CachingLexer, CLK_LexAfterModuleImport } CurLexerKind; @@ -224,10 +242,10 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { TokenLexer *TheTokenLexer; const DirectoryLookup *TheDirLookup; - IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, + IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, PreprocessorLexer* PPL, TokenLexer* TL, const DirectoryLookup *D) - : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), + : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL), TheDirLookup(D) {} }; std::vector<IncludeStackInfo> IncludeMacroStack; @@ -254,9 +272,9 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// reused for quick allocation. MacroArgs *MacroArgCache; friend class MacroArgs; - - /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma - /// push_macro directive, we keep a MacroInfo stack used to restore + + /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma + /// push_macro directive, we keep a MacroInfo stack used to restore /// previous macro value. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; @@ -286,12 +304,12 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack; /// \brief A record of the macro definitions and expansions that - /// occurred during preprocessing. + /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with /// \c createPreprocessingRecord() prior to preprocessing. PreprocessingRecord *Record; - + private: // Cached tokens state. typedef SmallVector<Token, 1> CachedTokensTy; @@ -325,7 +343,7 @@ private: // Cached tokens state. MacroInfoChain *MICache; MacroInfo *getInfoForMacro(IdentifierInfo *II) const; - + public: Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, @@ -333,7 +351,8 @@ public: ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup = 0, bool OwnsHeaderSearch = false, - bool DelayInitialization = false); + bool DelayInitialization = false, + bool IncrProcessing = false); ~Preprocessor(); @@ -342,11 +361,11 @@ public: /// /// \param Target Information about the target. void Initialize(const TargetInfo &Target); - + DiagnosticsEngine &getDiagnostics() const { return *Diags; } void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; } - const LangOptions &getLangOptions() const { return Features; } + const LangOptions &getLangOpts() const { return LangOpts; } const TargetInfo &getTargetInfo() const { return *Target; } FileManager &getFileManager() const { return FileMgr; } SourceManager &getSourceManager() const { return SourceMgr; } @@ -371,7 +390,7 @@ public: /// \brief Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } - + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { @@ -389,11 +408,6 @@ public: return SuppressIncludeNotFoundError; } - /// \brief Specify whether automatic module imports are enabled. - void setAutoModuleImport(bool AutoModuleImport = true) { - this->AutoModuleImport = AutoModuleImport; - } - /// isCurrentLexer - Return true if we are lexing directly from the specified /// lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { @@ -425,13 +439,14 @@ public: MacroInfo *getMacroInfo(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; - + return getInfoForMacro(II); } /// setMacroInfo - Specify a macro for this identifier. /// - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); + void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, + bool LoadedFromAST = false); /// macro_iterator/macro_begin/macro_end - This allows you to walk the current /// state of the macro table. This visits every currently-defined macro. @@ -484,29 +499,29 @@ public: void setCodeCompletionHandler(CodeCompletionHandler &Handler) { CodeComplete = &Handler; } - + /// \brief Retrieve the current code-completion handler. CodeCompletionHandler *getCodeCompletionHandler() const { return CodeComplete; } - + /// \brief Clear out the code completion handler. void clearCodeCompletionHandler() { CodeComplete = 0; } - + /// \brief Hook used by the lexer to invoke the "natural language" code /// completion point. void CodeCompleteNaturalLanguage(); - + /// \brief Retrieve the preprocessing record, or NULL if there is no /// preprocessing record. PreprocessingRecord *getPreprocessingRecord() const { return Record; } - - /// \brief Create a new preprocessing record, which will keep track of + + /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(bool IncludeNestedMacroExpansions); - + void createPreprocessingRecord(bool RecordConditionalDirectives); + /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); @@ -588,7 +603,7 @@ public: } void LexAfterModuleImport(Token &Result); - + /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get /// something not a comment. This is useful in -E -C mode where comments /// would foul up preprocessor directive handling. @@ -681,6 +696,18 @@ public: CachedTokens[CachedLexPos-1] = Tok; } + /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ + /// CurTokenLexer pointers. + void recomputeCurLexerKind(); + + /// \brief Returns true if incremental processing is enabled + bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; } + + /// \brief Enables the incremental processing + void enableIncrementalProcessing(bool value = true) { + IncrementalProcessing = value; + } + /// \brief Specify the point at which code-completion will be performed. /// /// \param File the file in which code completion should occur. If @@ -745,11 +772,11 @@ public: /// /// \brief StartOfLine Whether skipping these bytes puts the lexer at the /// start of a line. - void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { + void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { SkipMainFilePreamble.first = Bytes; SkipMainFilePreamble.second = StartOfLine; } - + /// Diag - Forwarding function for diagnostics. This emits a diagnostic at /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. @@ -771,7 +798,7 @@ public: StringRef getSpelling(SourceLocation loc, SmallVectorImpl<char> &buffer, bool *invalid = 0) const { - return Lexer::getSpelling(loc, buffer, SourceMgr, Features, invalid); + return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a @@ -782,7 +809,7 @@ public: /// /// \param Invalid If non-null, will be set \c true if an error occurs. std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { - return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid); + return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid); } /// getSpelling - This method is used to get the spelling of a token into a @@ -795,21 +822,21 @@ public: /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. - unsigned getSpelling(const Token &Tok, const char *&Buffer, + unsigned getSpelling(const Token &Tok, const char *&Buffer, bool *Invalid = 0) const { - return Lexer::getSpelling(Tok, Buffer, SourceMgr, Features, Invalid); + return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid); } /// 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. StringRef getSpelling(const Token &Tok, - SmallVectorImpl<char> &Buffer, - bool *Invalid = 0) const; + SmallVectorImpl<char> &Buffer, + bool *Invalid = 0) const; /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant /// with length 1, return the character. - char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, + char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, bool *Invalid = 0) const { assert(Tok.is(tok::numeric_constant) && Tok.getLength() == 1 && "Called on unsupported token"); @@ -824,6 +851,17 @@ public: return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid); } + /// \brief Retrieve the name of the immediate macro expansion. + /// + /// This routine starts from a source location, and finds the name of the macro + /// responsible for its immediate expansion. It looks through any intervening + /// macro argument expansions to compute this. It returns a StringRef which + /// refers to the SourceManager-owned buffer of the source where that macro + /// name is spelled. Thus, the result shouldn't out-live the SourceManager. + StringRef getImmediateMacroName(SourceLocation Loc) { + return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts()); + } + /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source /// location provides a location of the expansion point of the token. @@ -847,19 +885,28 @@ public: /// location pointing just past the end of the token; an offset of 1 produces /// a source location pointing to the last character in the token, etc. SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) { - return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features); + return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts); } /// \brief Returns true if the given MacroID location points at the first /// token of the macro expansion. - bool isAtStartOfMacroExpansion(SourceLocation loc) const { - return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, Features); + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// begin location of the macro. + bool isAtStartOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroBegin = 0) const { + return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, + MacroBegin); } /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. - bool isAtEndOfMacroExpansion(SourceLocation loc) const { - return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, Features); + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// end location of the macro. + bool isAtEndOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroEnd = 0) const { + return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd); } /// DumpToken - Print the token to stderr, used for debugging. @@ -872,7 +919,7 @@ public: /// token, return a new location that specifies a character within the token. SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const { - return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, Features); + return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts); } /// IncrementPasteCounter - Increment the counters for the number of token @@ -930,9 +977,18 @@ public: private: /// Identifiers used for SEH handling in Borland. These are only /// allowed in particular circumstances - IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block - IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression - IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally + // __except block + IdentifierInfo *Ident__exception_code, + *Ident___exception_code, + *Ident_GetExceptionCode; + // __except filter expression + IdentifierInfo *Ident__exception_info, + *Ident___exception_info, + *Ident_GetExceptionInfo; + // __finally + IdentifierInfo *Ident__abnormal_termination, + *Ident___abnormal_termination, + *Ident_AbnormalTermination; public: void PoisonSEHIdentifiers(bool Poison = true); // Borland @@ -976,6 +1032,9 @@ public: unsigned getCounterValue() const { return CounterValue; } void setCounterValue(unsigned V) { CounterValue = V; } + /// \brief Retrieves the module that we're currently building, if any. + Module *getCurrentModule(); + /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide /// SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); @@ -999,7 +1058,8 @@ public: const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule); + Module **SuggestedModule, + bool SkipCache = false); /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to @@ -1020,7 +1080,7 @@ public: /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds /// and consumes the EOD marker. - bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer, + bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer, SourceLocation &End); /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is @@ -1063,9 +1123,10 @@ private: /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro /// definition has just been read. Lex the rest of the arguments and the - /// closing ), updating MI with what we learn. Return true if an error occurs - /// parsing the arg list. - bool ReadMacroDefinitionArgList(MacroInfo *MI); + /// closing ), updating MI with what we learn and saving in LastTok the + /// last token read. + /// Return true if an error occurs parsing the arg list. + bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok); /// SkipExcludedConditionalBlock - We just read a #if or related directive and /// decided that the subsequent tokens are in the #if'd out portion of the @@ -1163,7 +1224,7 @@ private: bool InCachingLexMode() const { // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means // that we are past EOF, not that we are in CachingLex mode. - return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 && + return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 && !IncludeMacroStack.empty(); } void EnterCachingLexMode(); @@ -1182,8 +1243,9 @@ private: void HandleDigitDirective(Token &Tok); void HandleUserDiagnosticDirective(Token &Tok, bool isWarning); void HandleIdentSCCSDirective(Token &Tok); - void HandleMacroExportDirective(Token &Tok); - + void HandleMacroPublicDirective(Token &Tok); + void HandleMacroPrivateDirective(Token &Tok); + // File inclusion. void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok, @@ -1192,6 +1254,7 @@ private: void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); void HandleImportDirective(SourceLocation HashLoc, Token &Tok); + void HandleMicrosoftImportDirective(Token &Tok); // Macro handling. void HandleDefineDirective(Token &Tok); @@ -1217,6 +1280,7 @@ public: void HandlePragmaMessage(Token &MessageTok); void HandlePragmaPushMacro(Token &Tok); void HandlePragmaPopMacro(Token &Tok); + void HandlePragmaIncludeAlias(Token &Tok); IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok); // Return true and store the first token only if any CommentHandler diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h index e2e30bf..b551cd4 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h @@ -24,6 +24,7 @@ class FileEntry; class Preprocessor; class PreprocessorLexer { + virtual void anchor(); protected: Preprocessor *PP; // Preprocessor object controlling lexing. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Token.h b/contrib/llvm/tools/clang/include/clang/Lex/Token.h index e6dd160..a88f607 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Token.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h @@ -75,7 +75,8 @@ public: LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. - LeadingEmptyMacro = 0x10 // Empty macro exists before this token. + LeadingEmptyMacro = 0x10, // Empty macro exists before this token. + HasUDSuffix = 0x20 // This string or character literal has a ud-suffix. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -263,6 +264,9 @@ public: return (Flags & LeadingEmptyMacro) ? true : false; } + /// \brief Return true if this token is a string or character literal which + /// has a ud-suffix. + bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; } }; /// PPConditionalInfo - Information about the conditional stack (#if directives) diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h index 7253870..2405a0c 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h @@ -36,11 +36,13 @@ namespace clang { void ParseAST(Preprocessor &pp, ASTConsumer *C, ASTContext &Ctx, bool PrintStats = false, TranslationUnitKind TUKind = TU_Complete, - CodeCompleteConsumer *CompletionConsumer = 0); + CodeCompleteConsumer *CompletionConsumer = 0, + bool SkipFunctionBodies = false); /// \brief Parse the main file known to the preprocessor, producing an /// abstract syntax tree. - void ParseAST(Sema &S, bool PrintStats = false); + void ParseAST(Sema &S, bool PrintStats = false, + bool SkipFunctionBodies = false); } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h index 0e76c61..0d47292 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define PARSESTART #include "clang/Basic/DiagnosticParseKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h index 0046f88..dff8510 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h @@ -20,9 +20,10 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Sema/Sema.h" #include "clang/Sema/DeclSpec.h" -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PrettyStackTrace.h" #include <stack> namespace clang { @@ -36,7 +37,7 @@ namespace clang { class InMessageExpressionRAIIObject; class PoisonSEHIdentifiersRAIIObject; class VersionTuple; - + /// PrettyStackTraceParserEntry - If a crash happens while the parser is active, /// an entry is printed for it. class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { @@ -96,7 +97,7 @@ class Parser : public CodeCompletionHandler { unsigned short ParenCount, BracketCount, BraceCount; /// Actions - These are the callbacks we invoke as we parse various constructs - /// in the file. + /// in the file. Sema &Actions; DiagnosticsEngine &Diags; @@ -108,9 +109,21 @@ class Parser : public CodeCompletionHandler { /// Identifiers used for SEH handling in Borland. These are only /// allowed in particular circumstances - IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block - IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression - IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally + // __except block + IdentifierInfo *Ident__exception_code, + *Ident___exception_code, + *Ident_GetExceptionCode; + // __except filter expression + IdentifierInfo *Ident__exception_info, + *Ident___exception_info, + *Ident_GetExceptionInfo; + // __finally + IdentifierInfo *Ident__abnormal_termination, + *Ident___abnormal_termination, + *Ident_AbnormalTermination; + + /// Contextual keywords for Microsoft extensions. + IdentifierInfo *Ident__except; /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. @@ -123,7 +136,7 @@ class Parser : public CodeCompletionHandler { /// Objective-C contextual keywords. mutable IdentifierInfo *Ident_instancetype; - + /// \brief Identifier for "introduced". IdentifierInfo *Ident_introduced; @@ -135,43 +148,47 @@ class Parser : public CodeCompletionHandler { /// \brief Identifier for "unavailable". IdentifierInfo *Ident_unavailable; + + /// \brief Identifier for "message". + IdentifierInfo *Ident_message; - /// C++0x contextual keywords. + /// C++0x contextual keywords. mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; - llvm::OwningPtr<PragmaHandler> AlignHandler; - llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler; - llvm::OwningPtr<PragmaHandler> OptionsHandler; - llvm::OwningPtr<PragmaHandler> PackHandler; - llvm::OwningPtr<PragmaHandler> MSStructHandler; - llvm::OwningPtr<PragmaHandler> UnusedHandler; - llvm::OwningPtr<PragmaHandler> WeakHandler; - llvm::OwningPtr<PragmaHandler> FPContractHandler; - llvm::OwningPtr<PragmaHandler> OpenCLExtensionHandler; + OwningPtr<PragmaHandler> AlignHandler; + OwningPtr<PragmaHandler> GCCVisibilityHandler; + OwningPtr<PragmaHandler> OptionsHandler; + OwningPtr<PragmaHandler> PackHandler; + OwningPtr<PragmaHandler> MSStructHandler; + OwningPtr<PragmaHandler> UnusedHandler; + OwningPtr<PragmaHandler> WeakHandler; + OwningPtr<PragmaHandler> RedefineExtnameHandler; + OwningPtr<PragmaHandler> FPContractHandler; + OwningPtr<PragmaHandler> OpenCLExtensionHandler; /// Whether the '>' token acts as an operator or not. This will be /// true except when we are parsing an expression within a C++ /// template argument list, where the '>' closes the template /// argument list. bool GreaterThanIsOperator; - + /// ColonIsSacred - When this is false, we aggressively try to recover from /// code like "foo : bar" as if it were a typo for "foo :: bar". This is not /// safe in case statements and a few other things. This is managed by the /// ColonProtectionRAIIObject RAII object. bool ColonIsSacred; - /// \brief When true, we are directly inside an Objective-C messsage + /// \brief When true, we are directly inside an Objective-C messsage /// send expression. /// /// This is managed by the \c InMessageExpressionRAIIObject class, and /// should not be set directly. bool InMessageExpression; - + /// The "depth" of the template parameters currently being parsed. unsigned TemplateParameterDepth; - + /// Factory object for creating AttributeList objects. AttributeFactory AttrFactory; @@ -179,20 +196,24 @@ class Parser : public CodeCompletionHandler { /// declaration is finished. DelayedCleanupPool TopLevelDeclCleanupPool; + IdentifierInfo *getSEHExceptKeyword(); + + bool SkipFunctionBodies; + public: - Parser(Preprocessor &PP, Sema &Actions); + Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser(); - const LangOptions &getLang() const { return PP.getLangOptions(); } + const LangOptions &getLangOpts() const { return PP.getLangOpts(); } const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } Preprocessor &getPreprocessor() const { return PP; } Sema &getActions() const { return Actions; } const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } - + Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); } - + // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; @@ -241,8 +262,6 @@ public: /// the EOF was encountered. bool ParseTopLevelDecl(DeclGroupPtrTy &Result); - DeclGroupPtrTy FinishPendingObjCActions(); - private: //===--------------------------------------------------------------------===// // Low-Level token peeking and consumption methods. @@ -271,10 +290,9 @@ private: Tok.getKind() == tok::utf32_string_literal; } - /// \brief Returns true if the current token is a '=' or '==' and - /// false otherwise. If it's '==', we assume that it's a typo and we emit - /// DiagID and a fixit hint to turn '==' -> '='. - bool isTokenEqualOrMistypedEqualEqual(unsigned DiagID); + /// \brief Returns true if the current token is '=' or is a type of '='. + /// For typos, give a fixit to '=' + bool isTokenEqualOrEqualTypo(); /// ConsumeToken - Consume the current 'peek token' and lex the next one. /// This does not work with all kinds of tokens: strings and specific other @@ -370,9 +388,9 @@ private: assert(Tok.is(tok::code_completion)); PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); - return PrevTokLocation; + return PrevTokLocation; } - + ///\ brief When we are consuming a code-completion token without having /// matched specific position in the grammar, provide code-completion results /// based on context. @@ -391,6 +409,14 @@ private: /// \brief Handle the annotation token produced for #pragma unused(...) void HandlePragmaUnused(); + /// \brief Handle the annotation token produced for + /// #pragma GCC visibility... + void HandlePragmaVisibility(); + + /// \brief Handle the annotation token produced for + /// #pragma pack... + void HandlePragmaPack(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. @@ -409,83 +435,77 @@ private: return PP.LookAhead(0); } - /// \brief Tracks information about the current nesting depth of - /// opening delimiters of each kind. - class DelimiterTracker { - private: - friend class Parser; - - unsigned Paren, Brace, Square, Less, LLLess; - unsigned& get(tok::TokenKind t) { - switch (t) { - default: llvm_unreachable("Unexpected balanced token"); - case tok::l_brace: return Brace; - case tok::l_paren: return Paren; - case tok::l_square: return Square; - case tok::less: return Less; - case tok::lesslessless: return LLLess; - } - } - - void push(tok::TokenKind t) { - get(t)++; - } - - void pop(tok::TokenKind t) { - get(t)--; - } - - unsigned getDepth(tok::TokenKind t) { - return get(t); - } - - public: - DelimiterTracker() : Paren(0), Brace(0), Square(0), Less(0), LLLess(0) { } - }; - /// \brief RAII class that helps handle the parsing of an open/close delimiter /// pair, such as braces { ... } or parentheses ( ... ). class BalancedDelimiterTracker { - tok::TokenKind Kind, Close; Parser& P; - bool Cleanup; - const unsigned MaxDepth; + tok::TokenKind Kind, Close; + SourceLocation (Parser::*Consumer)(); SourceLocation LOpen, LClose; - - void assignClosingDelimiter() { + + unsigned short &getDepth() { switch (Kind) { - default: llvm_unreachable("Unexpected balanced token"); - case tok::l_brace: Close = tok::r_brace; break; - case tok::l_paren: Close = tok::r_paren; break; - case tok::l_square: Close = tok::r_square; break; - case tok::less: Close = tok::greater; break; - case tok::lesslessless: Close = tok::greatergreatergreater; break; + case tok::l_brace: return P.BraceCount; + case tok::l_square: return P.BracketCount; + case tok::l_paren: return P.ParenCount; + default: llvm_unreachable("Wrong token kind"); } } - + + enum { MaxDepth = 512 }; + + bool diagnoseOverflow(); + bool diagnoseMissingClose(); + public: - BalancedDelimiterTracker(Parser& p, tok::TokenKind k) - : Kind(k), P(p), Cleanup(false), MaxDepth(256) { - assignClosingDelimiter(); - } - - ~BalancedDelimiterTracker() { - if (Cleanup) - P.QuantityTracker.pop(Kind); + BalancedDelimiterTracker(Parser& p, tok::TokenKind k) : P(p), Kind(k) { + switch (Kind) { + default: llvm_unreachable("Unexpected balanced token"); + case tok::l_brace: + Close = tok::r_brace; + Consumer = &Parser::ConsumeBrace; + break; + case tok::l_paren: + Close = tok::r_paren; + Consumer = &Parser::ConsumeParen; + break; + + case tok::l_square: + Close = tok::r_square; + Consumer = &Parser::ConsumeBracket; + break; + } } SourceLocation getOpenLocation() const { return LOpen; } SourceLocation getCloseLocation() const { return LClose; } SourceRange getRange() const { return SourceRange(LOpen, LClose); } - bool consumeOpen(); - bool expectAndConsume(unsigned DiagID, - const char *Msg = "", + bool consumeOpen() { + if (!P.Tok.is(Kind)) + return true; + + if (getDepth() < MaxDepth) { + LOpen = (P.*Consumer)(); + return false; + } + + return diagnoseOverflow(); + } + + bool expectAndConsume(unsigned DiagID, + const char *Msg = "", tok::TokenKind SkipToTok = tok::unknown); - bool consumeClose(); - }; + bool consumeClose() { + if (P.Tok.is(Close)) { + LClose = (P.*Consumer)(); + return false; + } - DelimiterTracker QuantityTracker; + return diagnoseMissingClose(); + } + void skipToEnd(); + }; /// getTypeAnnotation - Read a parsed type out of an annotation token. static ParsedType getTypeAnnotation(Token &Tok) { @@ -495,16 +515,16 @@ private: static void setTypeAnnotation(Token &Tok, ParsedType T) { Tok.setAnnotationValue(T.getAsOpaquePtr()); } - + /// \brief Read an already-translated primary expression out of an annotation /// token. static ExprResult getExprAnnotation(Token &Tok) { if (Tok.getAnnotationValue()) return ExprResult((Expr *)Tok.getAnnotationValue()); - + return ExprResult(true); } - + /// \brief Set the primary expression corresponding to the given annotation /// token. static void setExprAnnotation(Token &Tok, ExprResult ER) { @@ -526,11 +546,11 @@ private: bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, bool &isInvalid) { - if (!getLang().AltiVec || + if (!getLangOpts().AltiVec || (Tok.getIdentifierInfo() != Ident_vector && Tok.getIdentifierInfo() != Ident_pixel)) return false; - + return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid); } @@ -538,11 +558,11 @@ private: /// identifier token, replacing it with the non-context-sensitive __vector. /// This returns true if the token was replaced. bool TryAltiVecVectorToken() { - if (!getLang().AltiVec || + if (!getLangOpts().AltiVec || Tok.getIdentifierInfo() != Ident_vector) return false; return TryAltiVecVectorTokenOutOfLine(); } - + bool TryAltiVecVectorTokenOutOfLine(); bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, @@ -598,14 +618,14 @@ private: Parser &P; Decl *DC; public: - explicit ObjCDeclContextSwitch(Parser &p) : P(p), + explicit ObjCDeclContextSwitch(Parser &p) : P(p), DC(p.getObjCDeclContext()) { if (DC) - P.Actions.ActOnObjCTemporaryExitContainerContext(); + P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC)); } ~ObjCDeclContextSwitch() { if (DC) - P.Actions.ActOnObjCReenterContainerContext(); + P.Actions.ActOnObjCReenterContainerContext(cast<DeclContext>(DC)); } }; @@ -625,7 +645,7 @@ private: /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior /// to the semicolon, consumes that extra token. bool ExpectAndConsumeSemi(unsigned DiagID); - + //===--------------------------------------------------------------------===// // Scope manipulation @@ -695,6 +715,7 @@ public: private: void SuggestParentheses(SourceLocation Loc, unsigned DK, SourceRange ParenRange); + void CheckNestedObjCContexts(SourceLocation AtLoc); /// SkipUntil - Read tokens until we get to the specified token, then consume /// it (unless DontConsume is true). Because we cannot guarantee that the @@ -706,16 +727,26 @@ private: /// returns false. bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true, bool DontConsume = false, bool StopAtCodeCompletion = false) { - return SkipUntil(&T, 1, StopAtSemi, DontConsume, StopAtCodeCompletion); + return SkipUntil(llvm::makeArrayRef(T), StopAtSemi, DontConsume, + StopAtCodeCompletion); } bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true, bool DontConsume = false, bool StopAtCodeCompletion = false) { tok::TokenKind TokArray[] = {T1, T2}; - return SkipUntil(TokArray, 2, StopAtSemi, DontConsume,StopAtCodeCompletion); + return SkipUntil(TokArray, StopAtSemi, DontConsume,StopAtCodeCompletion); } - bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, + bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, tok::TokenKind T3, bool StopAtSemi = true, bool DontConsume = false, - bool StopAtCodeCompletion = false); + bool StopAtCodeCompletion = false) { + tok::TokenKind TokArray[] = {T1, T2, T3}; + return SkipUntil(TokArray, StopAtSemi, DontConsume,StopAtCodeCompletion); + } + bool SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi = true, + bool DontConsume = false, bool StopAtCodeCompletion = false); + + /// SkipMalformedDecl - Read tokens until we get to some likely good stopping + /// point for skipping past a simple-declaration. + void SkipMalformedDecl(); //===--------------------------------------------------------------------===// // Lexing and parsing of C++ inline methods. @@ -757,9 +788,9 @@ private: ParsingClass *Class; }; - /// Contains the lexed tokens of an attribute with arguments that - /// may reference member variables and so need to be parsed at the - /// end of the class declaration after parsing all other member + /// Contains the lexed tokens of an attribute with arguments that + /// may reference member variables and so need to be parsed at the + /// end of the class declaration after parsing all other member /// member declarations. /// FIXME: Perhaps we should change the name of LateParsedDeclaration to /// LateParsedTokens. @@ -768,15 +799,15 @@ private: CachedTokens Toks; IdentifierInfo &AttrName; SourceLocation AttrNameLoc; - Decl *D; + SmallVector<Decl*, 2> Decls; - explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name, + explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name, SourceLocation Loc) - : Self(P), AttrName(Name), AttrNameLoc(Loc), D(0) {} + : Self(P), AttrName(Name), AttrNameLoc(Loc) {} virtual void ParseLexedAttributes(); - void setDecl(Decl *Dec) { D = Dec; } + void addDecl(Decl *D) { Decls.push_back(D); } }; /// A list of late parsed attributes. Used by ParseGNUAttributes. @@ -872,8 +903,9 @@ private: /// C++ class, its method declarations that contain parts that won't be /// parsed until after the definition is completed (C++ [class.mem]p2), /// the method declarations and possibly attached inline definitions - /// will be stored here with the tokens that will be parsed to create those entities. - typedef SmallVector<LateParsedDeclaration*, 2> LateParsedDeclarationsContainer; + /// will be stored here with the tokens that will be parsed to create those + /// entities. + typedef SmallVector<LateParsedDeclaration*,2> LateParsedDeclarationsContainer; /// \brief Representation of a class that has been parsed, including /// any member function declarations or definitions that need to be @@ -965,7 +997,7 @@ private: Popped = Other.Popped; Other.Popped = true; } - + void push() { State = Actions.PushParsingDeclaration(); Popped = false; @@ -1060,7 +1092,7 @@ private: bool isSpecialization, bool lastParameterListWasEmpty = false) : Kind(isSpecialization? ExplicitSpecialization : Template), - TemplateParams(TemplateParams), + TemplateParams(TemplateParams), LastParameterListWasEmpty(lastParameterListWasEmpty) { } explicit ParsedTemplateInfo(SourceLocation ExternLoc, @@ -1092,23 +1124,23 @@ private: /// \brief The location of the 'template' keyword, for an explicit /// instantiation. SourceLocation TemplateLoc; - + /// \brief Whether the last template parameter list was empty. bool LastParameterListWasEmpty; - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; }; /// \brief Contains a late templated function. /// Will be parsed at the end of the translation unit. struct LateParsedTemplatedFunction { - explicit LateParsedTemplatedFunction(Parser* P, Decl *MD) + explicit LateParsedTemplatedFunction(Decl *MD) : D(MD) {} CachedTokens Toks; - + /// \brief The template function declaration to be late parsed. - Decl *D; + Decl *D; }; void LexTemplateFunctionForLateParsing(CachedTokens &Toks); @@ -1128,10 +1160,15 @@ private: Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, ExprResult& Init); + const VirtSpecifiers& VS, + FunctionDefinitionKind DefinitionKind, + ExprResult& Init); void ParseCXXNonStaticMemberInitializer(Decl *VarD); void ParseLexedAttributes(ParsingClass &Class); - void ParseLexedAttribute(LateParsedAttribute &LA); + void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, + bool EnterScope, bool OnDefinition); + void ParseLexedAttribute(LateParsedAttribute &LA, + bool EnterScope, bool OnDefinition); void ParseLexedMethodDeclarations(ParsingClass &Class); void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM); void ParseLexedMethodDefs(ParsingClass &Class); @@ -1168,9 +1205,10 @@ private: AccessSpecifier AS = AS_none); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, AccessSpecifier AS = AS_none); - + Decl *ParseFunctionDefinition(ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + LateParsedAttrList *LateParsedAttrs = 0); void ParseKNRParamDeclarations(Declarator &D); // EndLoc, if non-NULL, is filled with the location of the last token of // the simple-asm. @@ -1178,9 +1216,9 @@ private: ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations - Parser::DeclGroupPtrTy ParseObjCAtDirectives(); - Parser::DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); - Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, + DeclGroupPtrTy ParseObjCAtDirectives(); + DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); + Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); void ParseObjCClassInstanceVariables(Decl *interfaceDecl, tok::ObjCKeywordKind visibility, @@ -1193,15 +1231,31 @@ private: bool ParseObjCProtocolQualifiers(DeclSpec &DS); void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, Decl *CDecl); - Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc, - ParsedAttributes &prefixAttrs); + DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc, + ParsedAttributes &prefixAttrs); + + struct ObjCImplParsingDataRAII { + Parser &P; + Decl *Dcl; + typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer; + LateParsedObjCMethodContainer LateParsedObjCMethods; + + ObjCImplParsingDataRAII(Parser &parser, Decl *D) + : P(parser), Dcl(D) { + P.CurParsedObjCImpl = this; + Finished = false; + } + ~ObjCImplParsingDataRAII(); - Decl *ObjCImpDecl; - SmallVector<Decl *, 4> PendingObjCImpDecl; - typedef SmallVector<LexedMethod*, 2> LateParsedObjCMethodContainer; - LateParsedObjCMethodContainer LateParsedObjCMethods; + void finish(SourceRange AtEnd); + bool isFinished() const { return Finished; } + + private: + bool Finished; + }; + ObjCImplParsingDataRAII *CurParsedObjCImpl; - Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc); + DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc); DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd); Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc); Decl *ParseObjCPropertySynthesize(SourceLocation atLoc); @@ -1232,11 +1286,18 @@ private: //===--------------------------------------------------------------------===// // C99 6.5: Expressions. - - ExprResult ParseExpression(); - ExprResult ParseConstantExpression(); + + /// TypeCastState - State whether an expression is or may be a type cast. + enum TypeCastState { + NotTypeCast = 0, + MaybeTypeCast, + IsTypeCast + }; + + ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); // Expr that doesn't include commas. - ExprResult ParseAssignmentExpression(); + ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); @@ -1247,10 +1308,10 @@ private: ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, - bool isTypeCast); + TypeCastState isTypeCast); ExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand = false, - bool isTypeCast = false); + TypeCastState isTypeCast = NotTypeCast); /// Returns true if the next token would start a postfix-expression /// suffix. @@ -1278,8 +1339,7 @@ private: SmallVectorImpl<SourceLocation> &CommaLocs, void (Sema::*Completer)(Scope *S, Expr *Data, - Expr **Args, - unsigned NumArgs) = 0, + llvm::ArrayRef<Expr *> Args) = 0, Expr *Data = 0); /// ParenParseOption - Control what ParseParenExpression will parse. @@ -1302,9 +1362,11 @@ private: SourceLocation LParenLoc, SourceLocation RParenLoc); - ExprResult ParseStringLiteralExpression(); + ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false); ExprResult ParseGenericSelectionExpression(); + + ExprResult ParseObjCBoolLiteral(); //===--------------------------------------------------------------------===// // C++ Expressions @@ -1420,6 +1482,7 @@ private: return ParseAssignmentExpression(); return ParseBraceInitializer(); } + bool MayBeDesignationStart(); ExprResult ParseBraceInitializer(); ExprResult ParseInitializerWithPotentialDesignator(); @@ -1432,29 +1495,35 @@ private: // Objective-C Expressions ExprResult ParseObjCAtExpression(SourceLocation AtLocation); ExprResult ParseObjCStringLiteral(SourceLocation AtLoc); + ExprResult ParseObjCCharacterLiteral(SourceLocation AtLoc); + ExprResult ParseObjCNumericLiteral(SourceLocation AtLoc); + ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue); + ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc); + ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc); ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); bool isSimpleObjCMessageExpression(); ExprResult ParseObjCMessageExpression(); ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, - SourceLocation SuperLoc, - ParsedType ReceiverType, - ExprArg ReceiverExpr); + SourceLocation SuperLoc, + ParsedType ReceiverType, + ExprArg ReceiverExpr); ExprResult ParseAssignmentExprWithObjCMessageExprStart( SourceLocation LBracloc, SourceLocation SuperLoc, ParsedType ReceiverType, ExprArg ReceiverExpr); bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr); - + //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks. - StmtResult ParseStatement() { + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = NULL) { StmtVector Stmts(Actions); - return ParseStatementOrDeclaration(Stmts, true); + return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc); } StmtResult ParseStatementOrDeclaration(StmtVector& Stmts, - bool OnlyStatement = false); + bool OnlyStatement, + SourceLocation *TrailingElseLoc = NULL); StmtResult ParseExprStatement(ParsedAttributes &Attrs); StmtResult ParseLabeledStatement(ParsedAttributes &Attr); StmtResult ParseCaseStatement(ParsedAttributes &Attr, @@ -1471,22 +1540,61 @@ private: Decl *&DeclResult, SourceLocation Loc, bool ConvertToBoolean); - StmtResult ParseIfStatement(ParsedAttributes &Attr); - StmtResult ParseSwitchStatement(ParsedAttributes &Attr); - StmtResult ParseWhileStatement(ParsedAttributes &Attr); + StmtResult ParseIfStatement(ParsedAttributes &Attr, + SourceLocation *TrailingElseLoc); + StmtResult ParseSwitchStatement(ParsedAttributes &Attr, + SourceLocation *TrailingElseLoc); + StmtResult ParseWhileStatement(ParsedAttributes &Attr, + SourceLocation *TrailingElseLoc); StmtResult ParseDoStatement(ParsedAttributes &Attr); - StmtResult ParseForStatement(ParsedAttributes &Attr); + StmtResult ParseForStatement(ParsedAttributes &Attr, + SourceLocation *TrailingElseLoc); StmtResult ParseGotoStatement(ParsedAttributes &Attr); StmtResult ParseContinueStatement(ParsedAttributes &Attr); StmtResult ParseBreakStatement(ParsedAttributes &Attr); StmtResult ParseReturnStatement(ParsedAttributes &Attr); StmtResult ParseAsmStatement(bool &msAsm); StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc); - bool ParseMicrosoftIfExistsCondition(bool& Result); + + /// \brief Describes the behavior that should be taken for an __if_exists + /// block. + enum IfExistsBehavior { + /// \brief Parse the block; this code is always used. + IEB_Parse, + /// \brief Skip the block entirely; this code is never used. + IEB_Skip, + /// \brief Parse the block as a dependent block, which may be used in + /// some template instantiations but not others. + IEB_Dependent + }; + + /// \brief Describes the condition of a Microsoft __if_exists or + /// __if_not_exists block. + struct IfExistsCondition { + /// \brief The location of the initial keyword. + SourceLocation KeywordLoc; + /// \brief Whether this is an __if_exists block (rather than an + /// __if_not_exists block). + bool IsIfExists; + + /// \brief Nested-name-specifier preceding the name. + CXXScopeSpec SS; + + /// \brief The name we're looking for. + UnqualifiedId Name; + + /// \brief The behavior of this __if_exists or __if_not_exists block + /// should. + IfExistsBehavior Behavior; +}; + + bool ParseMicrosoftIfExistsCondition(IfExistsCondition& Result); void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); void ParseMicrosoftIfExistsExternalDeclaration(); void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, AccessSpecifier& CurAS); + bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, + bool &InitExprsOk); bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, SmallVectorImpl<Expr *> &Constraints, SmallVectorImpl<Expr *> &Exprs); @@ -1525,6 +1633,8 @@ private: enum DeclSpecContext { DSC_normal, // normal context DSC_class, // class context, enables 'friend' + DSC_type_specifier, // C++ type-specifier-seq + DSC_trailing, // C++11 trailing-type-specifier in a trailing return type DSC_top_level // top-level/namespace declaration context }; @@ -1546,13 +1656,14 @@ private: ParsedAttributes &attrs, bool RequireSemi, ForRangeInit *FRI = 0); + bool MightBeDeclarator(unsigned Context); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, SourceLocation *DeclEnd = 0, ForRangeInit *FRI = 0); Decl *ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - bool ParseAttributesAfterDeclarator(Declarator &D); + bool ParseAsmAttributesAfterDeclarator(Declarator &D); Decl *ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); @@ -1562,30 +1673,27 @@ private: /// unless the body contains the code-completion point. /// /// \returns true if the function body was skipped. - bool trySkippingFunctionBodyForCodeCompletion(); + bool trySkippingFunctionBody(); bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS); + AccessSpecifier AS, DeclSpecContext DSC); DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context); void ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DSC_normal); - bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid, - const char *&PrevSpec, - unsigned &DiagID, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - bool SuppressDeclarations = false); + DeclSpecContext DSC = DSC_normal, + LateParsedAttrList *LateAttrs = 0); - void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none); + void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DSC_normal); void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, Declarator::TheContext Context); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - AccessSpecifier AS = AS_none); + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, DeclSpecContext DSC); void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, Decl *TagDecl); @@ -1604,7 +1712,7 @@ private: bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); 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. @@ -1614,25 +1722,25 @@ private: /// expression statement, when parsing function bodies. /// Returns true for declaration, false for expression. bool isDeclarationStatement() { - if (getLang().CPlusPlus) + if (getLangOpts().CPlusPlus) return isCXXDeclarationStatement(); return isDeclarationSpecifier(true); } - /// isSimpleDeclaration - Disambiguates between a declaration or an - /// expression, mainly used for the C 'clause-1' or the C++ + /// isForInitDeclaration - Disambiguates between a declaration or an + /// expression in the context of the C 'clause-1' or the C++ // 'for-init-statement' part of a 'for' statement. /// Returns true for declaration, false for expression. - bool isSimpleDeclaration() { - if (getLang().CPlusPlus) - return isCXXSimpleDeclaration(); + bool isForInitDeclaration() { + if (getLangOpts().CPlusPlus) + return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true); return isDeclarationSpecifier(true); } /// \brief Determine whether we are currently at the start of an Objective-C /// class message that appears to be missing the open bracket '['. bool isStartOfObjCClassMessageMissingOpenBracket(); - + /// \brief Starting with a scope specifier, identifier, or /// template-id that refers to the current class, determine whether /// this is a constructor declarator. @@ -1650,7 +1758,7 @@ private: /// whether the parens contain an expression or a type-id. /// Returns true for a type-id and false for an expression. bool isTypeIdInParens(bool &isAmbiguous) { - if (getLang().CPlusPlus) + if (getLangOpts().CPlusPlus) return isCXXTypeId(TypeIdInParens, isAmbiguous); isAmbiguous = false; return isTypeSpecifierQualifier(); @@ -1670,7 +1778,7 @@ private: /// If during the disambiguation process a parsing error is encountered, /// the function returns true to let the declaration parsing code handle it. /// Returns false if the statement is disambiguated as expression. - bool isCXXSimpleDeclaration(); + bool isCXXSimpleDeclaration(bool AllowForRangeDecl); /// isCXXFunctionDeclarator - Disambiguates between a function declarator or /// a constructor-style initializer, when parsing declaration statements. @@ -1732,10 +1840,12 @@ private: /// declaration specifier, TPResult::False() if it is not, /// TPResult::Ambiguous() if it could be either a decl-specifier or a /// function-style cast, and TPResult::Error() if a parsing error was - /// encountered. + /// encountered. If it could be a braced C++11 function-style cast, returns + /// BracedCastResult. /// Doesn't consume tokens. - TPResult isCXXDeclarationSpecifier(); - + TPResult + isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False()); + // "Tentative parsing" functions, used for disambiguation. If a parsing error // is encountered they will return TPResult::Error(). // Returning TPResult::True()/False() indicates that the ambiguity was @@ -1744,7 +1854,7 @@ private: // They all consume tokens, so backtracking should be used after calling them. TPResult TryParseDeclarationSpecifier(); - TPResult TryParseSimpleDeclaration(); + TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl); TPResult TryParseTypeofSpecifier(); TPResult TryParseProtocolQualifiers(); TPResult TryParseInitDeclaratorList(); @@ -1760,6 +1870,16 @@ private: Decl **OwnedType = 0); void ParseBlockId(); + // Check for the start of a C++11 attribute-specifier-seq in a context where + // an attribute is not allowed. + bool CheckProhibitedCXX11Attribute() { + assert(Tok.is(tok::l_square)); + if (!getLangOpts().CPlusPlus0x || NextToken().isNot(tok::l_square)) + return false; + return DiagnoseProhibitedCXX11Attribute(); + } + bool DiagnoseProhibitedCXX11Attribute(); + void ProhibitAttributes(ParsedAttributesWithRange &attrs) { if (!attrs.Range.isValid()) return; DiagnoseProhibitedAttributes(attrs); @@ -1790,35 +1910,38 @@ private: SourceLocation *EndLoc); void MaybeParseCXX0XAttributes(Declarator &D) { - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { + if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; - ParseCXX0XAttributes(attrs, &endLoc); + ParseCXX11Attributes(attrs, &endLoc); D.takeAttributes(attrs, endLoc); } } void MaybeParseCXX0XAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { + if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrsWithRange(AttrFactory); - ParseCXX0XAttributes(attrsWithRange, endLoc); + ParseCXX11Attributes(attrsWithRange, endLoc); attrs.takeAllFrom(attrsWithRange); } } void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs, - SourceLocation *endLoc = 0) { - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) - ParseCXX0XAttributes(attrs, endLoc); + SourceLocation *endLoc = 0, + bool OuterMightBeMessageSend = false) { + if (getLangOpts().CPlusPlus0x && + isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) + ParseCXX11Attributes(attrs, endLoc); } - void ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, + void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, SourceLocation *EndLoc = 0); - void ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, + void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = 0); + IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc); void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { - if (getLang().MicrosoftExt && Tok.is(tok::l_square)) + if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square)) ParseMicrosoftAttributes(attrs, endLoc); } void ParseMicrosoftAttributes(ParsedAttributes &attrs, @@ -1843,15 +1966,22 @@ private: void ParseTypeofSpecifier(DeclSpec &DS); - void ParseDecltypeSpecifier(DeclSpec &DS); + SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); + void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, + SourceLocation StartLoc, + SourceLocation EndLoc); void ParseUnderlyingTypeSpecifier(DeclSpec &DS); void ParseAtomicSpecifier(DeclSpec &DS); - ExprResult ParseAlignArgument(SourceLocation Start); + ExprResult ParseAlignArgument(SourceLocation Start, + SourceLocation &EllipsisLoc); void ParseAlignmentSpecifier(ParsedAttributes &Attrs, SourceLocation *endLoc = 0); - VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const; + VirtSpecifiers::Specifier isCXX0XVirtSpecifier(const Token &Tok) const; + VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const { + return isCXX0XVirtSpecifier(Tok); + } void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS); bool isCXX0XFinalKeyword() const; @@ -1918,9 +2048,20 @@ private: //===--------------------------------------------------------------------===// // C++ 7: Declarations [dcl.dcl] - bool isCXX0XAttributeSpecifier(bool FullLookahead = false, - tok::TokenKind *After = 0); - + /// The kind of attribute specifier we have found. + enum CXX11AttributeKind { + /// This is not an attribute specifier. + CAK_NotAttributeSpecifier, + /// This should be treated as an attribute-specifier. + CAK_AttributeSpecifier, + /// The next tokens are '[[', but this is not an attribute-specifier. This + /// is ill-formed by C++11 [dcl.attr.grammar]p6. + CAK_InvalidAttributeSpecifier + }; + CXX11AttributeKind + isCXX11AttributeSpecifier(bool Disambiguate = false, + bool OuterMightBeMessageSend = false); + Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd, SourceLocation InlineLoc = SourceLocation()); void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, @@ -1952,15 +2093,13 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. - TypeResult ParseClassName(SourceLocation &EndLocation, CXXScopeSpec &SS); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, - DeclSpec &DS, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - AccessSpecifier AS = AS_none, - bool SuppressDeclarations = false); + DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, bool EnteringContext, + DeclSpecContext DSC); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, Decl *TagDecl); - ExprResult ParseCXXMemberInitializer(bool IsFunction, + ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1972,18 +2111,20 @@ private: //===--------------------------------------------------------------------===// // C++ 10: Derived classes [class.derived] + TypeResult ParseBaseTypeSpecifier(SourceLocation &BaseLoc, + SourceLocation &EndLocation); void ParseBaseClause(Decl *ClassDecl); BaseResult ParseBaseSpecifier(Decl *ClassDecl); AccessSpecifier getAccessSpecifierIfPresent() const; - bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext, ParsedType ObjectType, UnqualifiedId &Id, - bool AssumeTemplateId, - SourceLocation TemplateKWLoc); + bool AssumeTemplateId); bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, ParsedType ObjectType, UnqualifiedId &Result); @@ -1991,8 +2132,9 @@ private: bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, + SourceLocation& TemplateKWLoc, UnqualifiedId &Result); - + //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] @@ -2036,27 +2178,30 @@ private: bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &TemplateName, - SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(); bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); - Decl *ParseExplicitInstantiation(SourceLocation ExternLoc, - SourceLocation TemplateLoc, - SourceLocation &DeclEnd); + Decl *ParseExplicitInstantiation(unsigned Context, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); //===--------------------------------------------------------------------===// // Modules - DeclGroupPtrTy ParseModuleImport(); - + DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc); + //===--------------------------------------------------------------------===// // GNU G++: Type Traits [Type-Traits.html in the GCC manual] ExprResult ParseUnaryTypeTrait(); ExprResult ParseBinaryTypeTrait(); - + ExprResult ParseTypeTrait(); + //===--------------------------------------------------------------------===// // Embarcadero: Arary and Expression Traits ExprResult ParseArrayTypeTrait(); diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h index 7a636e5..c9c92e3 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h @@ -31,6 +31,11 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning); +ASTConsumer *CreateModernObjCRewriter(const std::string &InFile, + raw_ostream *OS, + DiagnosticsEngine &Diags, + const LangOptions &LOpts, + bool SilenceRewriteMacroWarning); /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to /// HTML with syntax highlighting suitable for viewing in a web-browser. diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h index bf7e791..44f0611 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h @@ -18,6 +18,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Rewrite/Rewriter.h" +#include "clang/Edit/EditedSource.h" namespace clang { @@ -26,20 +27,38 @@ class FileEntry; class FixItOptions { public: + FixItOptions() : FixWhatYouCan(false), + FixOnlyWarnings(false), Silent(false) { } + virtual ~FixItOptions(); /// \brief This file is about to be rewritten. Return the name of the file /// that is okay to write to. - virtual std::string RewriteFilename(const std::string &Filename) = 0; + /// + /// \param fd out parameter for file descriptor. After the call it may be set + /// to an open file descriptor for the returned filename, or it will be -1 + /// otherwise. + /// + virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0; /// \brief Whether to abort fixing a file when not all errors could be fixed. bool FixWhatYouCan; + + /// \brief Whether to only fix warnings and not errors. + bool FixOnlyWarnings; + + /// \brief If true, only pass the diagnostic to the actual diagnostic consumer + /// if it is an error or a fixit was applied as part of the diagnostic. + /// It basically silences warnings without accompanying fixits. + bool Silent; }; class FixItRewriter : public DiagnosticConsumer { /// \brief The diagnostics machinery. DiagnosticsEngine &Diags; + edit::EditedSource Editor; + /// \brief The rewriter used to perform the various code /// modifications. Rewriter Rewrite; @@ -47,6 +66,7 @@ class FixItRewriter : public DiagnosticConsumer { /// \brief The diagnostic client that performs the actual formatting /// of error messages. DiagnosticConsumer *Client; + bool OwnsClient; /// \brief Turn an input path into an output path. NULL implies overwriting /// the original. @@ -55,6 +75,9 @@ class FixItRewriter : public DiagnosticConsumer { /// \brief The number of rewriter failures. unsigned NumFailures; + /// \brief Whether the previous diagnostic was not passed to the consumer. + bool PrevDiagSilenced; + public: typedef Rewriter::buffer_iterator iterator; @@ -82,7 +105,8 @@ public: /// \brief Write the modified source files. /// /// \returns true if there was an error, false otherwise. - bool WriteFixedFiles(); + bool WriteFixedFiles( + std::vector<std::pair<std::string, std::string> > *RewrittenFiles = 0); /// IncludeInDiagnosticCounts - This method (whose default implementation /// returns true) indicates whether the diagnostics handled by this diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h index f7aeefa..6e9ecac 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h @@ -28,8 +28,8 @@ protected: class FixItAction : public ASTFrontendAction { protected: - llvm::OwningPtr<FixItRewriter> Rewriter; - llvm::OwningPtr<FixItOptions> FixItOpts; + OwningPtr<FixItRewriter> Rewriter; + OwningPtr<FixItOptions> FixItOpts; virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile); @@ -46,6 +46,17 @@ public: ~FixItAction(); }; +/// \brief Emits changes to temporary files and uses them for the original +/// frontend action. +class FixItRecompile : public WrapperFrontendAction { +public: + FixItRecompile(FrontendAction *WrappedAction) + : WrapperFrontendAction(WrappedAction) {} + +protected: + virtual bool BeginInvocation(CompilerInstance &CI); +}; + class RewriteObjCAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h index 62ea12a..9ebd33a 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h @@ -41,7 +41,7 @@ namespace clang { /// ScratchBuf - This is the buffer that we create scratch tokens from. /// - llvm::OwningPtr<ScratchBuffer> ScratchBuf; + OwningPtr<ScratchBuffer> ScratchBuf; TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT void operator=(const TokenRewriter&); // DO NOT IMPLEMENT. diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h index bcacf7a..142f144 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h @@ -85,6 +85,8 @@ private: /// \brief The location of the 'unavailable' keyword in an /// availability attribute. SourceLocation UnavailableLoc; + + const Expr *MessageExpr; /// The next attribute in the current position. AttributeList *NextInPosition; @@ -138,13 +140,15 @@ private: const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, - SourceLocation unavailable, + SourceLocation unavailable, + const Expr *messageExpr, bool declspec, bool cxx0x) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), - UnavailableLoc(unavailable), NextInPosition(0), NextInPool(0) { + UnavailableLoc(unavailable), MessageExpr(messageExpr), + NextInPosition(0), NextInPool(0) { new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); @@ -155,122 +159,21 @@ private: friend class AttributeFactory; public: - enum Kind { // Please keep this list alphabetized. - AT_acquired_after, - AT_acquired_before, - AT_address_space, - AT_alias, - AT_aligned, - AT_always_inline, - AT_analyzer_noreturn, - AT_annotate, - AT_arc_weakref_unavailable, - AT_availability, // Clang-specific - AT_base_check, - AT_blocks, - AT_carries_dependency, - AT_cdecl, - AT_cf_audited_transfer, // Clang-specific. - AT_cf_consumed, // Clang-specific. - AT_cf_returns_autoreleased, // Clang-specific. - AT_cf_returns_not_retained, // Clang-specific. - AT_cf_returns_retained, // Clang-specific. - AT_cf_unknown_transfer, // Clang-specific. - AT_cleanup, - AT_common, - AT_const, - AT_constant, - AT_constructor, - AT_deprecated, - AT_destructor, - AT_device, - AT_dllexport, - AT_dllimport, - AT_exclusive_lock_function, - AT_exclusive_locks_required, - AT_exclusive_trylock_function, - AT_ext_vector_type, - AT_fastcall, - AT_format, - AT_format_arg, - AT_global, - AT_gnu_inline, - AT_guarded_by, - AT_guarded_var, - AT_host, - AT_IBAction, // Clang-specific. - AT_IBOutlet, // Clang-specific. - AT_IBOutletCollection, // Clang-specific. - AT_init_priority, - AT_launch_bounds, - AT_lock_returned, - AT_lockable, - AT_locks_excluded, - AT_malloc, - AT_may_alias, - AT_mode, - AT_MsStruct, - AT_naked, - AT_neon_polyvector_type, // Clang-specific. - AT_neon_vector_type, // Clang-specific. - AT_no_instrument_function, - AT_no_thread_safety_analysis, - AT_nocommon, - AT_nodebug, - AT_noinline, - AT_nonnull, - AT_noreturn, - AT_nothrow, - AT_ns_bridged, // Clang-specific. - AT_ns_consumed, // Clang-specific. - AT_ns_consumes_self, // Clang-specific. - AT_ns_returns_autoreleased, // Clang-specific. - AT_ns_returns_not_retained, // Clang-specific. - AT_ns_returns_retained, // Clang-specific. - AT_nsobject, - AT_objc_exception, - AT_objc_gc, - AT_objc_method_family, - AT_objc_ownership, // Clang-specific. - AT_objc_precise_lifetime, // Clang-specific. - AT_objc_returns_inner_pointer, // Clang-specific. - AT_opencl_image_access, // OpenCL-specific. - AT_opencl_kernel_function, // OpenCL-specific. - AT_overloadable, // Clang-specific. - AT_ownership_holds, // Clang-specific. - AT_ownership_returns, // Clang-specific. - AT_ownership_takes, // Clang-specific. - AT_packed, - AT_pascal, - AT_pcs, // ARM specific - AT_pt_guarded_by, - AT_pt_guarded_var, - AT_pure, - AT_regparm, - AT_reqd_wg_size, - AT_scoped_lockable, - AT_section, - AT_sentinel, - AT_shared, - AT_shared_lock_function, - AT_shared_locks_required, - AT_shared_trylock_function, - AT_stdcall, - AT_thiscall, - AT_transparent_union, - AT_unavailable, - AT_unlock_function, - AT_unused, - AT_used, - AT_uuid, - AT_vecreturn, // PS3 PPU-specific. - AT_vector_size, - AT_visibility, - AT_warn_unused_result, - AT_weak, - AT_weak_import, - AT_weakref, - AT_returns_twice, + enum Kind { + #define PARSED_ATTR(NAME) AT_##NAME, + #include "clang/Sema/AttrParsedAttrList.inc" + PARSED_ATTR(address_space) + PARSED_ATTR(base_check) + PARSED_ATTR(cf_returns_autoreleased) + PARSED_ATTR(ext_vector_type) + PARSED_ATTR(mode) + PARSED_ATTR(neon_polyvector_type) + PARSED_ATTR(neon_vector_type) + PARSED_ATTR(objc_gc) + PARSED_ATTR(objc_ownership) + PARSED_ATTR(opencl_image_access) + PARSED_ATTR(vector_size) + #undef PARSED_ATTR IgnoredAttribute, UnknownAttribute }; @@ -371,6 +274,11 @@ public: assert(getKind() == AT_availability && "Not an availability attribute"); return UnavailableLoc; } + + const Expr * getMessageExpr() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return MessageExpr; + } }; /// A factory, from which one makes pools, from which one creates @@ -492,13 +400,14 @@ public: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, + const Expr *MessageExpr, bool declspec = false, bool cxx0x = false) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, introduced, deprecated, obsoleted, - unavailable, + unavailable, MessageExpr, declspec, cxx0x)); } @@ -616,10 +525,12 @@ public: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, + const Expr *MessageExpr, bool declspec = false, bool cxx0x = false) { AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, introduced, deprecated, obsoleted, unavailable, + MessageExpr, declspec, cxx0x); add(attr); return attr; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h index 9e2d60d..fe9bed5 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -24,14 +24,14 @@ namespace clang { class Decl; - + /// \brief Default priority values for code-completion results based /// on their kind. enum { /// \brief Priority for the next initialization in a constructor initializer /// list. CCP_NextInitializer = 7, - /// \brief Priority for an enumeration constant inside a switch whose + /// \brief Priority for an enumeration constant inside a switch whose /// condition is of the enumeration type. CCP_EnumInCase = 7, /// \brief Priority for a send-to-super completion. @@ -59,7 +59,7 @@ enum { /// \brief Priority for a result that isn't likely to be what the user wants, /// but is included for completeness. CCP_Unlikely = 80, - + /// \brief Priority for the Objective-C "_cmd" implicit parameter. CCP_ObjC_cmd = CCP_Unlikely }; @@ -76,15 +76,15 @@ enum { /// of the current method, which might imply that some kind of delegation /// is occurring. CCD_SelectorMatch = -3, - + /// \brief Adjustment to the "bool" type in Objective-C, where the typedef /// "BOOL" is preferred. CCD_bool_in_ObjC = 1, - + /// \brief Adjustment for KVC code pattern priorities when it doesn't look /// like the CCD_ProbablyNotObjCCollection = 15, - + /// \brief An Objective-C method being used as a property. CCD_MethodAsProperty = 2 }; @@ -114,14 +114,14 @@ enum SimplifiedTypeClass { STC_Record, STC_Void }; - + /// \brief Determine the simplified type class of the given canonical type. SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); - + /// \brief Determine the type that this declaration will have if it is used /// as a type or in an expression. QualType getDeclUsageType(ASTContext &C, NamedDecl *ND); - + /// \brief Determine the priority to be given to a macro code completion result /// with the given name. /// @@ -131,14 +131,14 @@ QualType getDeclUsageType(ASTContext &C, NamedDecl *ND); /// /// \param PreferredTypeIsPointer Whether the preferred type for the context /// of this macro is a pointer type. -unsigned getMacroUsagePriority(StringRef MacroName, +unsigned getMacroUsagePriority(StringRef MacroName, const LangOptions &LangOpts, bool PreferredTypeIsPointer = false); /// \brief Determine the libclang cursor kind associated with the given /// declaration. CXCursorKind getCursorKindForDecl(Decl *D); - + class FunctionDecl; class FunctionType; class FunctionTemplateDecl; @@ -182,22 +182,22 @@ public: /// \brief Code completion occurred on the right-hand side of a member /// access expression using the dot operator. /// - /// The results of this completion are the members of the type being - /// accessed. The type itself is available via + /// The results of this completion are the members of the type being + /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_DotMemberAccess, /// \brief Code completion occurred on the right-hand side of a member /// access expression using the arrow operator. /// - /// The results of this completion are the members of the type being - /// accessed. The type itself is available via + /// The results of this completion are the members of the type being + /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_ArrowMemberAccess, /// \brief Code completion occurred on the right-hand side of an Objective-C /// property access expression. /// - /// The results of this completion are the members of the type being - /// accessed. The type itself is available via + /// The results of this completion are the members of the type being + /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_ObjCPropertyAccess, /// \brief Code completion occurred after the "enum" keyword, to indicate @@ -228,7 +228,7 @@ public: CCC_MacroNameUse, /// \brief Code completion occurred within a preprocessor expression. CCC_PreprocessorExpression, - /// \brief Code completion occurred where a preprocessor directive is + /// \brief Code completion occurred where a preprocessor directive is /// expected. CCC_PreprocessorDirective, /// \brief Code completion occurred in a context where natural language is @@ -246,14 +246,14 @@ public: CCC_ParenthesizedExpression, /// \brief Code completion where an Objective-C instance message is expcted. CCC_ObjCInstanceMessage, - /// \brief Code completion where an Objective-C class message is expected. + /// \brief Code completion where an Objective-C class message is expected. CCC_ObjCClassMessage, /// \brief Code completion where the name of an Objective-C class is /// expected. CCC_ObjCInterfaceName, /// \brief Code completion where an Objective-C category name is expected. CCC_ObjCCategoryName, - /// \brief An unknown context, in which we are recovering from a parsing + /// \brief An unknown context, in which we are recovering from a parsing /// error and don't know which completions we should give. CCC_Recovery }; @@ -264,27 +264,27 @@ private: /// \brief The type that would prefer to see at this point (e.g., the type /// of an initializer or function parameter). QualType PreferredType; - + /// \brief The type of the base object in a member access expression. QualType BaseType; - + /// \brief The identifiers for Objective-C selector parts. IdentifierInfo **SelIdents; - + /// \brief The number of Objective-C selector parts. unsigned NumSelIdents; - + public: /// \brief Construct a new code-completion context of the given kind. - CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(NULL), + CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(NULL), NumSelIdents(0) { } - + /// \brief Construct a new code-completion context of the given kind. CodeCompletionContext(enum Kind Kind, QualType T, IdentifierInfo **SelIdents = NULL, unsigned NumSelIdents = 0) : Kind(Kind), SelIdents(SelIdents), - NumSelIdents(NumSelIdents) { + NumSelIdents(NumSelIdents) { if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess || Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage || Kind == CCC_ObjCInstanceMessage) @@ -292,22 +292,22 @@ public: else PreferredType = T; } - + /// \brief Retrieve the kind of code-completion context. enum Kind getKind() const { return Kind; } - + /// \brief Retrieve the type that this expression would prefer to have, e.g., /// if the expression is a variable initializer or a function argument, the /// type of the corresponding variable or function parameter. QualType getPreferredType() const { return PreferredType; } - - /// \brief Retrieve the type of the base object in a member-access + + /// \brief Retrieve the type of the base object in a member-access /// expression. QualType getBaseType() const { return BaseType; } - + /// \brief Retrieve the Objective-C selector identifiers. IdentifierInfo **getSelIdents() const { return SelIdents; } - + /// \brief Retrieve the number of Objective-C selector identifiers. unsigned getNumSelIdents() const { return NumSelIdents; } @@ -320,10 +320,10 @@ public: /// \brief A "string" used to describe how code completion can /// be performed for an entity. /// -/// A code completion string typically shows how a particular entity can be +/// A code completion string typically shows how a particular entity can be /// used. For example, the code completion string for a function would show -/// the syntax to call it, including the parentheses, placeholders for the -/// arguments, etc. +/// the syntax to call it, including the parentheses, placeholders for the +/// arguments, etc. class CodeCompletionString { public: /// \brief The different kinds of "chunks" that can occur within a code @@ -340,7 +340,7 @@ public: /// an optional code completion string that describes the default arguments /// in a function call. CK_Optional, - /// \brief A string that acts as a placeholder for, e.g., a function + /// \brief A string that acts as a placeholder for, e.g., a function /// call argument. CK_Placeholder, /// \brief A piece of text that describes something about the result but @@ -383,30 +383,30 @@ public: /// platform). CK_VerticalSpace }; - + /// \brief One piece of the code completion string. struct Chunk { - /// \brief The kind of data stored in this piece of the code completion + /// \brief The kind of data stored in this piece of the code completion /// string. ChunkKind Kind; - + union { /// \brief The text string associated with a CK_Text, CK_Placeholder, /// CK_Informative, or CK_Comma chunk. - /// The string is owned by the chunk and will be deallocated + /// The string is owned by the chunk and will be deallocated /// (with delete[]) when the chunk is destroyed. const char *Text; - + /// \brief The code completion string associated with a CK_Optional chunk. /// The optional code completion string is owned by the chunk, and will /// be deallocated (with delete) when the chunk is destroyed. CodeCompletionString *Optional; }; - + Chunk() : Kind(CK_Text), Text(0) { } - - Chunk(ChunkKind Kind, const char *Text = ""); - + + explicit Chunk(ChunkKind Kind, const char *Text = ""); + /// \brief Create a new text chunk. static Chunk CreateText(const char *Text); @@ -425,49 +425,56 @@ public: /// \brief Create a new current-parameter chunk. static Chunk CreateCurrentParameter(const char *CurrentParameter); }; - + private: /// \brief The number of chunks stored in this string. unsigned NumChunks : 16; - + /// \brief The number of annotations for this code-completion result. unsigned NumAnnotations : 16; /// \brief The priority of this code-completion string. - unsigned Priority : 30; - + unsigned Priority : 16; + /// \brief The availability of this code-completion result. unsigned Availability : 2; + /// \brief The kind of the parent context. + unsigned ParentKind : 14; + + /// \brief The name of the parent context. + StringRef ParentName; + CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT CodeCompletionString &operator=(const CodeCompletionString &); // DITTO - + CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, unsigned Priority, CXAvailabilityKind Availability, - const char **Annotations, unsigned NumAnnotations); + const char **Annotations, unsigned NumAnnotations, + CXCursorKind ParentKind, StringRef ParentName); ~CodeCompletionString() { } - + friend class CodeCompletionBuilder; friend class CodeCompletionResult; - + public: typedef const Chunk *iterator; iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); } iterator end() const { return begin() + NumChunks; } bool empty() const { return NumChunks == 0; } unsigned size() const { return NumChunks; } - + const Chunk &operator[](unsigned I) const { assert(I < size() && "Chunk index out-of-range"); return begin()[I]; } - + /// \brief Returns the text in the TypedText chunk. const char *getTypedText() const; /// \brief Retrieve the priority of this code completion result. unsigned getPriority() const { return Priority; } - + /// \brief Retrieve the availability of this code completion result. unsigned getAvailability() const { return Availability; } @@ -476,106 +483,156 @@ public: /// \brief Retrieve the annotation string specified by \c AnnotationNr. const char *getAnnotation(unsigned AnnotationNr) const; + + /// \brief Retrieve parent context's cursor kind. + CXCursorKind getParentContextKind() const { + return (CXCursorKind)ParentKind; + } + + /// \brief Retrieve the name of the parent context. + StringRef getParentContextName() const { + return ParentName; + } /// \brief Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. - std::string getAsString() const; + std::string getAsString() const; }; /// \brief An allocator used specifically for the purpose of code completion. -class CodeCompletionAllocator : public llvm::BumpPtrAllocator { +class CodeCompletionAllocator : public llvm::BumpPtrAllocator { public: /// \brief Copy the given string into this allocator. const char *CopyString(StringRef String); /// \brief Copy the given string into this allocator. const char *CopyString(Twine String); - + // \brief Copy the given string into this allocator. const char *CopyString(const char *String) { return CopyString(StringRef(String)); } - + /// \brief Copy the given string into this allocator. const char *CopyString(const std::string &String) { return CopyString(StringRef(String)); } }; - + +/// \brief Allocator for a cached set of global code completions. +class GlobalCodeCompletionAllocator + : public CodeCompletionAllocator, + public RefCountedBase<GlobalCodeCompletionAllocator> +{ + +}; + +class CodeCompletionTUInfo { + llvm::DenseMap<DeclContext *, StringRef> ParentNames; + IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> AllocatorRef; + +public: + explicit CodeCompletionTUInfo( + IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> Allocator) + : AllocatorRef(Allocator) { } + + IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> getAllocatorRef() const { + return AllocatorRef; + } + CodeCompletionAllocator &getAllocator() const { + assert(AllocatorRef); + return *AllocatorRef; + } + + StringRef getParentName(DeclContext *DC); +}; + +} // end namespace clang + +namespace llvm { + template <> struct isPodLike<clang::CodeCompletionString::Chunk> { + static const bool value = true; + }; +} + +namespace clang { + /// \brief A builder class used to construct new code-completion strings. class CodeCompletionBuilder { -public: +public: typedef CodeCompletionString::Chunk Chunk; - + private: CodeCompletionAllocator &Allocator; + CodeCompletionTUInfo &CCTUInfo; unsigned Priority; CXAvailabilityKind Availability; + CXCursorKind ParentKind; + StringRef ParentName; /// \brief The chunks stored in this string. SmallVector<Chunk, 4> Chunks; SmallVector<const char *, 2> Annotations; - + public: - CodeCompletionBuilder(CodeCompletionAllocator &Allocator) - : Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){ - } - CodeCompletionBuilder(CodeCompletionAllocator &Allocator, - unsigned Priority, CXAvailabilityKind Availability) - : Allocator(Allocator), Priority(Priority), Availability(Availability) { } + CodeCompletionTUInfo &CCTUInfo) + : Allocator(Allocator), CCTUInfo(CCTUInfo), + Priority(0), Availability(CXAvailability_Available), + ParentKind(CXCursor_NotImplemented) { } + + CodeCompletionBuilder(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + unsigned Priority, CXAvailabilityKind Availability) + : Allocator(Allocator), CCTUInfo(CCTUInfo), + Priority(Priority), Availability(Availability), + ParentKind(CXCursor_NotImplemented) { } /// \brief Retrieve the allocator into which the code completion /// strings should be allocated. CodeCompletionAllocator &getAllocator() const { return Allocator; } - - /// \brief Take the resulting completion string. + + CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } + + /// \brief Take the resulting completion string. /// /// This operation can only be performed once. CodeCompletionString *TakeString(); - + /// \brief Add a new typed-text chunk. - void AddTypedTextChunk(const char *Text) { - Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); - } - + void AddTypedTextChunk(const char *Text); + /// \brief Add a new text chunk. - void AddTextChunk(const char *Text) { - Chunks.push_back(Chunk::CreateText(Text)); - } + void AddTextChunk(const char *Text); /// \brief Add a new optional chunk. - void AddOptionalChunk(CodeCompletionString *Optional) { - Chunks.push_back(Chunk::CreateOptional(Optional)); - } - + void AddOptionalChunk(CodeCompletionString *Optional); + /// \brief Add a new placeholder chunk. - void AddPlaceholderChunk(const char *Placeholder) { - Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); - } - + void AddPlaceholderChunk(const char *Placeholder); + /// \brief Add a new informative chunk. - void AddInformativeChunk(const char *Text) { - Chunks.push_back(Chunk::CreateInformative(Text)); - } - + void AddInformativeChunk(const char *Text); + /// \brief Add a new result-type chunk. - void AddResultTypeChunk(const char *ResultType) { - Chunks.push_back(Chunk::CreateResultType(ResultType)); - } - + void AddResultTypeChunk(const char *ResultType); + /// \brief Add a new current-parameter chunk. - void AddCurrentParameterChunk(const char *CurrentParameter) { - Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); - } - + void AddCurrentParameterChunk(const char *CurrentParameter); + /// \brief Add a new chunk. - void AddChunk(Chunk C) { Chunks.push_back(C); } + void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = ""); void AddAnnotation(const char *A) { Annotations.push_back(A); } -}; + + /// \brief Add the parent context information to this code completion. + void addParentContext(DeclContext *DC); + CXCursorKind getParentKind() const { return ParentKind; } + StringRef getParentName() const { return ParentName; } +}; + /// \brief Captures a result of code completion. class CodeCompletionResult { public: @@ -586,23 +643,23 @@ public: RK_Macro, //< Refers to a macro RK_Pattern //< Refers to a precomputed pattern. }; - + /// \brief The kind of result stored here. ResultKind Kind; - + + /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are + /// referring to. In the latter case, the declaration might be NULL. + NamedDecl *Declaration; + union { - /// \brief When Kind == RK_Declaration, the declaration we are referring - /// to. - NamedDecl *Declaration; - - /// \brief When Kind == RK_Keyword, the string representing the keyword + /// \brief When Kind == RK_Keyword, the string representing the keyword /// or symbol's spelling. const char *Keyword; - + /// \brief When Kind == RK_Pattern, the code-completion string that /// describes the completion text to insert. CodeCompletionString *Pattern; - + /// \brief When Kind == RK_Macro, the identifier that refers to a macro. IdentifierInfo *Macro; }; @@ -612,21 +669,21 @@ public: /// \brief The cursor kind that describes this result. CXCursorKind CursorKind; - + /// \brief The availability of this result. CXAvailabilityKind Availability; - + /// \brief Specifies which parameter (of a function, Objective-C method, /// macro, etc.) we should start with when formatting the result. unsigned StartParameter; - + /// \brief Whether this result is hidden by another name. bool Hidden : 1; - + /// \brief Whether this result was found via lookup into a base class. bool QualifierIsInformative : 1; - - /// \brief Whether this declaration is the beginning of a + + /// \brief Whether this declaration is the beginning of a /// nested-name-specifier and, therefore, should be followed by '::'. bool StartsNestedNameSpecifier : 1; @@ -637,43 +694,43 @@ public: /// \brief Whether we're completing a declaration of the given entity, /// rather than a use of that entity. bool DeclaringEntity : 1; - + /// \brief If the result should have a nested-name-specifier, this is it. - /// When \c QualifierIsInformative, the nested-name-specifier is + /// When \c QualifierIsInformative, the nested-name-specifier is /// informative rather than required. NestedNameSpecifier *Qualifier; - + /// \brief Build a result that refers to a declaration. - CodeCompletionResult(NamedDecl *Declaration, + CodeCompletionResult(NamedDecl *Declaration, NestedNameSpecifier *Qualifier = 0, bool QualifierIsInformative = false, bool Accessible = true) - : Kind(RK_Declaration), Declaration(Declaration), - Priority(getPriorityFromDecl(Declaration)), - Availability(CXAvailability_Available), StartParameter(0), + : Kind(RK_Declaration), Declaration(Declaration), + Priority(getPriorityFromDecl(Declaration)), + Availability(CXAvailability_Available), StartParameter(0), Hidden(false), QualifierIsInformative(QualifierIsInformative), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(Qualifier) { + DeclaringEntity(false), Qualifier(Qualifier) { computeCursorKindAndAvailability(Accessible); } - + /// \brief Build a result that refers to a keyword or symbol. CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword) - : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), - Availability(CXAvailability_Available), - StartParameter(0), Hidden(false), QualifierIsInformative(0), + : Kind(RK_Keyword), Declaration(0), Keyword(Keyword), Priority(Priority), + Availability(CXAvailability_Available), + StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) { computeCursorKindAndAvailability(); } - + /// \brief Build a result that refers to a macro. CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) - : Kind(RK_Macro), Macro(Macro), Priority(Priority), - Availability(CXAvailability_Available), StartParameter(0), - Hidden(false), QualifierIsInformative(0), + : Kind(RK_Macro), Declaration(0), Macro(Macro), Priority(Priority), + Availability(CXAvailability_Available), StartParameter(0), + Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { + DeclaringEntity(false), Qualifier(0) { computeCursorKindAndAvailability(); } @@ -681,27 +738,40 @@ public: CodeCompletionResult(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern, CXCursorKind CursorKind = CXCursor_NotImplemented, - CXAvailabilityKind Availability = CXAvailability_Available) - : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), - CursorKind(CursorKind), Availability(Availability), StartParameter(0), - Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) - { + CXAvailabilityKind Availability = CXAvailability_Available, + NamedDecl *D = 0) + : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority), + CursorKind(CursorKind), Availability(Availability), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(0) + { } - + + /// \brief Build a result that refers to a pattern with an associated + /// declaration. + CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D, + unsigned Priority) + : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority), + Availability(CXAvailability_Available), StartParameter(0), + Hidden(false), QualifierIsInformative(false), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(0) { + computeCursorKindAndAvailability(); + } + /// \brief Retrieve the declaration stored in this result. NamedDecl *getDeclaration() const { assert(Kind == RK_Declaration && "Not a declaration result"); return Declaration; } - + /// \brief Retrieve the keyword stored in this result. const char *getKeyword() const { assert(Kind == RK_Keyword && "Not a keyword result"); return Keyword; } - + /// \brief Create a new code-completion string that describes how to insert /// this result into a program. /// @@ -710,37 +780,42 @@ public: /// \param Allocator The allocator that will be used to allocate the /// string itself. CodeCompletionString *CreateCodeCompletionString(Sema &S, - CodeCompletionAllocator &Allocator); - + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo); + CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx, + Preprocessor &PP, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo); + /// \brief Determine a base priority for the given declaration. static unsigned getPriorityFromDecl(NamedDecl *ND); - + private: void computeCursorKindAndAvailability(bool Accessible = true); }; - + bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y); - -inline bool operator>(const CodeCompletionResult &X, + +inline bool operator>(const CodeCompletionResult &X, const CodeCompletionResult &Y) { return Y < X; } - -inline bool operator<=(const CodeCompletionResult &X, + +inline bool operator<=(const CodeCompletionResult &X, const CodeCompletionResult &Y) { return !(Y < X); } -inline bool operator>=(const CodeCompletionResult &X, +inline bool operator>=(const CodeCompletionResult &X, const CodeCompletionResult &Y) { return !(X < Y); } - -raw_ostream &operator<<(raw_ostream &OS, + +raw_ostream &operator<<(raw_ostream &OS, const CodeCompletionString &CCS); -/// \brief Abstract interface for a consumer of code-completion +/// \brief Abstract interface for a consumer of code-completion /// information. class CodeCompleteConsumer { protected: @@ -750,15 +825,15 @@ protected: /// \brief Whether to include code patterns (such as for loops) within /// the completion results. bool IncludeCodePatterns; - + /// \brief Whether to include global (top-level) declarations and names in /// the completion results. bool IncludeGlobals; - + /// \brief Whether the output format for the code-completion consumer is /// binary. bool OutputIsBinary; - + public: class OverloadCandidate { public: @@ -772,25 +847,25 @@ public: /// for which we only have a function prototype. CK_FunctionType }; - + private: /// \brief The kind of overload candidate. CandidateKind Kind; - + union { - /// \brief The function overload candidate, available when + /// \brief The function overload candidate, available when /// Kind == CK_Function. FunctionDecl *Function; - + /// \brief The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; - + /// \brief The function type that describes the entity being called, /// when Kind == CK_FunctionType. const FunctionType *Type; }; - + public: OverloadCandidate(FunctionDecl *Function) : Kind(CK_Function), Function(Function) { } @@ -803,55 +878,56 @@ public: /// \brief Determine the kind of overload candidate. CandidateKind getKind() const { return Kind; } - - /// \brief Retrieve the function overload candidate or the templated + + /// \brief Retrieve the function overload candidate or the templated /// function declaration for a function template. FunctionDecl *getFunction() const; - + /// \brief Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); return FunctionTemplate; } - + /// \brief Retrieve the function type of the entity, regardless of how the /// function is stored. const FunctionType *getFunctionType() const; - + /// \brief Create a new code-completion string that describes the function /// signature of this overload candidate. - CodeCompletionString *CreateSignatureString(unsigned CurrentArg, + CodeCompletionString *CreateSignatureString(unsigned CurrentArg, Sema &S, - CodeCompletionAllocator &Allocator) const; + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) const; }; - + CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false), IncludeGlobals(true), OutputIsBinary(false) { } - + CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, bool IncludeGlobals, bool OutputIsBinary) : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { } - + /// \brief Whether the code-completion consumer wants to see macros. bool includeMacros() const { return IncludeMacros; } /// \brief Whether the code-completion consumer wants to see code patterns. bool includeCodePatterns() const { return IncludeCodePatterns; } - + /// \brief Whether to include global (top-level) declaration results. bool includeGlobals() const { return IncludeGlobals; } - + /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } - + /// \brief Deregisters and destroys this code-completion consumer. virtual ~CodeCompleteConsumer(); /// \name Code-completion callbacks //@{ /// \brief Process the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, + virtual void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, CodeCompletionResult *Results, unsigned NumResults) { } @@ -868,20 +944,22 @@ public: OverloadCandidate *Candidates, unsigned NumCandidates) { } //@} - + /// \brief Retrieve the allocator that will be used to allocate /// code completion strings. virtual CodeCompletionAllocator &getAllocator() = 0; + + virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 0; }; -/// \brief A simple code-completion consumer that prints the results it +/// \brief A simple code-completion consumer that prints the results it /// receives in a simple format. class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { /// \brief The raw output stream. raw_ostream &OS; - - CodeCompletionAllocator Allocator; - + + CodeCompletionTUInfo CCTUInfo; + public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. @@ -889,21 +967,26 @@ public: bool IncludeGlobals, raw_ostream &OS) : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, - false), OS(OS) {} - + false), OS(OS), + CCTUInfo(new GlobalCodeCompletionAllocator) {} + /// \brief Prints the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Sema &S, + virtual void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, CodeCompletionResult *Results, unsigned NumResults); - + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, - unsigned NumCandidates); - - virtual CodeCompletionAllocator &getAllocator() { return Allocator; } + unsigned NumCandidates); + + virtual CodeCompletionAllocator &getAllocator() { + return CCTUInfo.getAllocator(); + } + + virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() { return CCTUInfo; } }; - + } // end namespace clang #endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h index 3260a70..67fd393 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h @@ -25,9 +25,11 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/Lex/Token.h" #include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/Lambda.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" namespace clang { @@ -243,6 +245,7 @@ public: static const TST TST_char16 = clang::TST_char16; static const TST TST_char32 = clang::TST_char32; static const TST TST_int = clang::TST_int; + static const TST TST_int128 = clang::TST_int128; static const TST TST_half = clang::TST_half; static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; @@ -445,7 +448,10 @@ public: CXXScopeSpec &getTypeSpecScope() { return TypeScope; } const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; } - const SourceRange &getSourceRange() const { return Range; } + const SourceRange &getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } @@ -609,6 +615,11 @@ public: bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + void ClearConstexprSpec() { + Constexpr_specified = false; + ConstexprLoc = SourceLocation(); + } + AttributePool &getAttributePool() const { return Attrs.getPool(); } @@ -962,9 +973,11 @@ public: void setTemplateId(TemplateIdAnnotation *TemplateId); /// \brief Return the source range that covers this unqualified-id. - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(StartLocation, EndLocation); } + SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; } + SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; } }; /// CachedTokens - A set of tokens that has been cached for later @@ -1105,6 +1118,16 @@ struct DeclaratorChunk { /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; + /// \brief The location of the const-qualifier, if any. + /// + /// If this is an invalid location, there is no const-qualifier. + unsigned ConstQualifierLoc; + + /// \brief The location of the volatile-qualifier, if any. + /// + /// If this is an invalid location, there is no volatile-qualifier. + unsigned VolatileQualifierLoc; + /// \brief The location of the 'mutable' qualifer in a lambda-declarator, if /// any. unsigned MutableLoc; @@ -1170,6 +1193,16 @@ struct DeclaratorChunk { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } + /// \brief Retrieve the location of the ref-qualifier, if any. + SourceLocation getConstQualifierLoc() const { + return SourceLocation::getFromRawEncoding(ConstQualifierLoc); + } + + /// \brief Retrieve the location of the ref-qualifier, if any. + SourceLocation getVolatileQualifierLoc() const { + return SourceLocation::getFromRawEncoding(VolatileQualifierLoc); + } + /// \brief Retrieve the location of the 'mutable' qualifier, if any. SourceLocation getMutableLoc() const { return SourceLocation::getFromRawEncoding(MutableLoc); @@ -1230,7 +1263,6 @@ struct DeclaratorChunk { void destroy() { switch (Kind) { - default: llvm_unreachable("Unknown decl type!"); case DeclaratorChunk::Function: return Fun.destroy(); case DeclaratorChunk::Pointer: return Ptr.destroy(); case DeclaratorChunk::BlockPointer: return Cls.destroy(); @@ -1306,6 +1338,8 @@ struct DeclaratorChunk { unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, + SourceLocation ConstQualifierLoc, + SourceLocation VolatileQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, SourceLocation ESpecLoc, @@ -1357,6 +1391,15 @@ struct DeclaratorChunk { }; +/// \brief Described the kind of function definition (if any) provided for +/// a function. +enum FunctionDefinitionKind { + FDK_Declaration, + FDK_Definition, + FDK_Defaulted, + FDK_Deleted +}; + /// Declarator - Information about one declarator, including the parsed type /// information and the identifier. When the declarator is fully formed, this /// is turned into the appropriate Decl object. @@ -1385,9 +1428,11 @@ public: CXXCatchContext, // C++ catch exception-declaration ObjCCatchContext, // Objective-C catch exception-declaration BlockLiteralContext, // Block literal declarator. + LambdaExprContext, // Lambda-expression declarator. + TrailingReturnContext, // C++11 trailing-type-specifier. TemplateTypeArgContext, // Template type argument. - AliasDeclContext, // C++0x alias-declaration. - AliasTemplateContext // C++0x alias-declaration template. + AliasDeclContext, // C++11 alias-declaration. + AliasTemplateContext // C++11 alias-declaration template. }; private: @@ -1412,8 +1457,11 @@ private: /// GroupingParens - Set by Parser::ParseParenDeclarator(). bool GroupingParens : 1; - /// FunctionDefinition - Is this Declarator for a function or member defintion - bool FunctionDefinition : 1; + /// FunctionDefinition - Is this Declarator for a function or member + /// definition and, if so, what kind? + /// + /// Actually a FunctionDefinitionKind. + unsigned FunctionDefinition : 2; // Redeclaration - Is this Declarator is a redeclaration. bool Redeclaration : 1; @@ -1433,6 +1481,10 @@ private: /// Extension - true if the declaration is preceded by __extension__. bool Extension : 1; + /// \brief If this is the second or subsequent declarator in this declaration, + /// the location of the comma before this declarator. + SourceLocation CommaLoc; + /// \brief If provided, the source location of the ellipsis used to describe /// this declarator as a parameter pack. SourceLocation EllipsisLoc; @@ -1443,7 +1495,8 @@ public: Declarator(const DeclSpec &ds, TheContext C) : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), - GroupingParens(false), FunctionDefinition(false), Redeclaration(false), + GroupingParens(false), FunctionDefinition(FDK_Declaration), + Redeclaration(false), Attrs(ds.getAttributePool().getFactory()), AsmLabel(0), InlineParamsUsed(false), Extension(false) { } @@ -1484,7 +1537,9 @@ public: } /// getSourceRange - Get the source range that spans this declarator. - const SourceRange &getSourceRange() const { return Range; } + const SourceRange &getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } void SetSourceRange(SourceRange R) { Range = R; } /// SetRangeBegin - Set the start of the source range to Loc, unless it's @@ -1521,6 +1576,8 @@ public: Attrs.clear(); AsmLabel = 0; InlineParamsUsed = false; + CommaLoc = SourceLocation(); + EllipsisLoc = SourceLocation(); } /// mayOmitIdentifier - Return true if the identifier is either optional or @@ -1547,7 +1604,9 @@ public: case CXXCatchContext: case ObjCCatchContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: + case TrailingReturnContext: return true; } llvm_unreachable("unknown context kind!"); @@ -1577,7 +1636,9 @@ public: case ObjCParameterContext: case ObjCResultContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: + case TrailingReturnContext: return false; } llvm_unreachable("unknown context kind!"); @@ -1588,15 +1649,31 @@ public: bool mayBeFollowedByCXXDirectInit() const { if (hasGroupingParens()) return false; + if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return false; + + if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern && + Context != FileContext) + return false; + + // Special names can't have direct initializers. + if (Name.getKind() != UnqualifiedId::IK_Identifier) + return false; + switch (Context) { case FileContext: case BlockContext: case ForContext: return true; + case ConditionContext: + // This may not be followed by a direct initializer, but it can't be a + // function declaration either, and we'd prefer to perform a tentative + // parse in order to produce the right diagnostic. + return true; + case KNRTypeListContext: case MemberContext: - case ConditionContext: case PrototypeContext: case ObjCParameterContext: case ObjCResultContext: @@ -1608,7 +1685,9 @@ public: case AliasDeclContext: case AliasTemplateContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: + case TrailingReturnContext: return false; } llvm_unreachable("unknown context kind!"); @@ -1696,7 +1775,6 @@ public: return !DeclTypeInfo[i].Arr.NumElts; } llvm_unreachable("Invalid type chunk"); - return false; } return false; } @@ -1721,7 +1799,6 @@ public: return false; } llvm_unreachable("Invalid type chunk"); - return false; } return false; } @@ -1800,13 +1877,26 @@ public: void setGroupingParens(bool flag) { GroupingParens = flag; } bool hasGroupingParens() const { return GroupingParens; } - + + bool isFirstDeclarator() const { return !CommaLoc.isValid(); } + SourceLocation getCommaLoc() const { return CommaLoc; } + void setCommaLoc(SourceLocation CL) { CommaLoc = CL; } + bool hasEllipsis() const { return EllipsisLoc.isValid(); } SourceLocation getEllipsisLoc() const { return EllipsisLoc; } void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; } - void setFunctionDefinition(bool Val) { FunctionDefinition = Val; } - bool isFunctionDefinition() const { return FunctionDefinition; } + void setFunctionDefinitionKind(FunctionDefinitionKind Val) { + FunctionDefinition = Val; + } + + bool isFunctionDefinition() const { + return getFunctionDefinitionKind() != FDK_Declaration; + } + + FunctionDefinitionKind getFunctionDefinitionKind() const { + return (FunctionDefinitionKind)FunctionDefinition; + } void setRedeclaration(bool Val) { Redeclaration = Val; } bool isRedeclaration() const { return Redeclaration; } @@ -1855,38 +1945,24 @@ private: SourceLocation LastLocation; }; -/// LambdaCaptureDefault - The default, if any, capture method for a -/// lambda expression. -enum LambdaCaptureDefault { - LCD_None, - LCD_ByCopy, - LCD_ByRef -}; - -/// LambdaCaptureKind - The different capture forms in a lambda -/// introducer: 'this' or a copied or referenced variable. -enum LambdaCaptureKind { - LCK_This, - LCK_ByCopy, - LCK_ByRef -}; - /// LambdaCapture - An individual capture in a lambda introducer. struct LambdaCapture { LambdaCaptureKind Kind; SourceLocation Loc; IdentifierInfo* Id; - - LambdaCapture(LambdaCaptureKind Kind, - SourceLocation Loc, - IdentifierInfo* Id = 0) - : Kind(Kind), Loc(Loc), Id(Id) + SourceLocation EllipsisLoc; + + LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, + IdentifierInfo* Id = 0, + SourceLocation EllipsisLoc = SourceLocation()) + : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc) {} }; /// LambdaIntroducer - Represents a complete lambda introducer. struct LambdaIntroducer { SourceRange Range; + SourceLocation DefaultLoc; LambdaCaptureDefault Default; llvm::SmallVector<LambdaCapture, 4> Captures; @@ -1896,8 +1972,9 @@ struct LambdaIntroducer { /// addCapture - Append a capture in a lambda introducer. void addCapture(LambdaCaptureKind Kind, SourceLocation Loc, - IdentifierInfo* Id = 0) { - Captures.push_back(LambdaCapture(Kind, Loc, Id)); + IdentifierInfo* Id = 0, + SourceLocation EllipsisLoc = SourceLocation()) { + Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc)); } }; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h index dd2603d..3320cd8 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h @@ -122,8 +122,9 @@ public: void Destroy(); static DelayedDiagnostic makeDeprecation(SourceLocation Loc, - const NamedDecl *D, - StringRef Msg); + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + StringRef Msg); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { @@ -187,12 +188,17 @@ public: assert(Kind == ForbiddenType && "not a forbidden-type diagnostic"); return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType); } + + const ObjCInterfaceDecl *getUnknownObjCClass() const { + return DeprecationData.UnknownObjCClass; + } private: union { /// Deprecation. struct { const NamedDecl *Decl; + const ObjCInterfaceDecl *UnknownObjCClass; const char *Message; size_t MessageLen; } DeprecationData; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h index 7b83625..785bf6a 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h @@ -59,10 +59,7 @@ public: /// \brief Load the contents of the global method pool for a given /// selector. - /// - /// \returns a pair of Objective-C methods lists containing the - /// instance and factory methods, respectively, with this selector. - virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. diff --git a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h index 85d8ad2..dff0134 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H #include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/SmallVector.h" namespace clang { @@ -23,9 +24,11 @@ class ASTContext; class Decl; class DeclContext; class DeclarationName; +class ExternalPreprocessorSource; class NamedDecl; +class Preprocessor; class Scope; - + /// IdentifierResolver - Keeps track of shadowed decls on enclosing /// scopes. It manages the shadowing chains of declaration names and /// implements efficient decl lookup based on a declaration name. @@ -141,10 +144,10 @@ public: }; /// begin - Returns an iterator for decls with the name 'Name'. - static iterator begin(DeclarationName Name); + iterator begin(DeclarationName Name); /// end - Returns an iterator that has 'finished'. - static iterator end() { + iterator end() { return iterator(); } @@ -175,23 +178,29 @@ public: /// position. void InsertDeclAfter(iterator Pos, NamedDecl *D); - /// \brief Link the declaration into the chain of declarations for - /// the given identifier. + /// \brief Try to add the given declaration to the top level scope, if it + /// (or a redeclaration of it) hasn't already been added. /// - /// This is a lower-level routine used by the AST reader to link a - /// declaration into a specific IdentifierInfo before the - /// declaration actually has a name. - void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D); - - explicit IdentifierResolver(const LangOptions &LangOpt); + /// \param D The externally-produced declaration to add. + /// + /// \param Name The name of the externally-produced declaration. + /// + /// \returns true if the declaration was added, false otherwise. + bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name); + + explicit IdentifierResolver(Preprocessor &PP); ~IdentifierResolver(); private: const LangOptions &LangOpt; - + Preprocessor &PP; + class IdDeclInfoMap; IdDeclInfoMap *IdDeclInfos; + void updatingIdentifier(IdentifierInfo &II); + void readingIdentifier(IdentifierInfo &II); + /// FETokenInfo contains a Decl pointer if lower bit == 0. static inline bool isDeclPtr(void *Ptr) { return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h index e69bebd..4433843 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h @@ -1,4 +1,4 @@ -//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===// +//===--- Initialization.h - Semantic Analysis for Initializers --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -70,7 +70,10 @@ public: EK_BlockElement, /// \brief The entity being initialized is the real or imaginary part of a /// complex number. - EK_ComplexElement + EK_ComplexElement, + /// \brief The entity being initialized is the field that captures a + /// variable in a lambda. + EK_LambdaCapture }; private: @@ -85,7 +88,7 @@ private: QualType Type; union { - /// \brief When Kind == EK_Variable or EK_Member, the VarDecl or + /// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or /// FieldDecl, respectively. DeclaratorDecl *VariableOrMember; @@ -98,7 +101,7 @@ private: TypeSourceInfo *TypeInfo; struct { - /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the + /// \brief When Kind == EK_Result, EK_Exception, EK_New, the /// location of the 'return', 'throw', or 'new' keyword, /// respectively. When Kind == EK_Temporary, the location where /// the temporary is being created. @@ -118,6 +121,14 @@ private: /// EK_ComplexElement, the index of the array or vector element being /// initialized. unsigned Index; + + struct { + /// \brief The variable being captured by an EK_LambdaCapture. + VarDecl *Var; + + /// \brief The source location at which the capture occurs. + unsigned Location; + } Capture; }; InitializedEntity() { } @@ -147,6 +158,14 @@ private: InitializedEntity(ASTContext &Context, unsigned Index, const InitializedEntity &Parent); + /// \brief Create the initialization entity for a lambda capture. + InitializedEntity(VarDecl *Var, FieldDecl *Field, SourceLocation Loc) + : Kind(EK_LambdaCapture), Parent(0), Type(Field->getType()) + { + Capture.Var = Var; + Capture.Location = Loc.getRawEncoding(); + } + public: /// \brief Create the initialization entity for a variable. static InitializedEntity InitializeVariable(VarDecl *Var) { @@ -156,7 +175,7 @@ public: /// \brief Create the initialization entity for a parameter. static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm) { - bool Consumed = (Context.getLangOptions().ObjCAutoRefCount && + bool Consumed = (Context.getLangOpts().ObjCAutoRefCount && Parm->hasAttr<NSConsumedAttr>()); InitializedEntity Entity; @@ -246,6 +265,13 @@ public: return InitializedEntity(Context, Index, Parent); } + /// \brief Create the initialization entity for a lambda capture. + static InitializedEntity InitializeLambdaCapture(VarDecl *Var, + FieldDecl *Field, + SourceLocation Loc) { + return InitializedEntity(Var, Field, Loc); + } + /// \brief Determine the kind of initialization. EntityKind getKind() const { return Kind; } @@ -314,9 +340,22 @@ public: /// element, sets the element index. void setElementIndex(unsigned Index) { assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement || - EK_ComplexElement); + getKind() == EK_ComplexElement); this->Index = Index; } + + /// \brief Retrieve the variable for a captured variable in a lambda. + VarDecl *getCapturedVar() const { + assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); + return Capture.Var; + } + + /// \brief Determine the location of the capture when initializing + /// field from a captured variable in a lambda. + SourceLocation getCaptureLoc() const { + assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); + return SourceLocation::getFromRawEncoding(Capture.Location); + } }; /// \brief Describes the kind of initialization being performed, along with @@ -326,36 +365,36 @@ class InitializationKind { public: /// \brief The kind of initialization being performed. enum InitKind { - IK_Direct, ///< Direct initialization - IK_Copy, ///< Copy initialization - IK_Default, ///< Default initialization - IK_Value ///< Value initialization + IK_Direct, ///< Direct initialization + IK_DirectList, ///< Direct list-initialization + IK_Copy, ///< Copy initialization + IK_Default, ///< Default initialization + IK_Value ///< Value initialization }; private: - /// \brief The kind of initialization that we're storing. - enum StoredInitKind { - SIK_Direct = IK_Direct, ///< Direct initialization - SIK_Copy = IK_Copy, ///< Copy initialization - SIK_Default = IK_Default, ///< Default initialization - SIK_Value = IK_Value, ///< Value initialization - SIK_ImplicitValue, ///< Implicit value initialization - SIK_DirectCast, ///< Direct initialization due to a cast - /// \brief Direct initialization due to a C-style cast. - SIK_DirectCStyleCast, - /// \brief Direct initialization due to a functional-style cast. - SIK_DirectFunctionalCast + /// \brief The context of the initialization. + enum InitContext { + IC_Normal, ///< Normal context + IC_ExplicitConvs, ///< Normal context, but allows explicit conversion funcs + IC_Implicit, ///< Implicit context (value initialization) + IC_StaticCast, ///< Static cast context + IC_CStyleCast, ///< C-style cast context + IC_FunctionalCast ///< Functional cast context }; /// \brief The kind of initialization being performed. - StoredInitKind Kind; + InitKind Kind : 8; + + /// \brief The context of the initialization. + InitContext Context : 8; /// \brief The source locations involved in the initialization. SourceLocation Locations[3]; - InitializationKind(StoredInitKind Kind, SourceLocation Loc1, + InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1, SourceLocation Loc2, SourceLocation Loc3) - : Kind(Kind) + : Kind(Kind), Context(Context) { Locations[0] = Loc1; Locations[1] = Loc2; @@ -367,41 +406,53 @@ public: static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { - return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc); + return InitializationKind(IK_Direct, IC_Normal, + InitLoc, LParenLoc, RParenLoc); + } + + static InitializationKind CreateDirectList(SourceLocation InitLoc) { + return InitializationKind(IK_DirectList, IC_Normal, + InitLoc, InitLoc, InitLoc); } /// \brief Create a direct initialization due to a cast that isn't a C-style /// or functional cast. static InitializationKind CreateCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a C-style cast. static InitializationKind CreateCStyleCast(SourceLocation StartLoc, - SourceRange TypeRange) { - return InitializationKind(SIK_DirectCStyleCast, - StartLoc, TypeRange.getBegin(), + SourceRange TypeRange, + bool InitList) { + // C++ cast syntax doesn't permit init lists, but C compound literals are + // exactly that. + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_CStyleCast, StartLoc, TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a functional cast. - static InitializationKind CreateFunctionalCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectFunctionalCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + static InitializationKind CreateFunctionalCast(SourceRange TypeRange, + bool InitList) { + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_FunctionalCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a copy initialization. static InitializationKind CreateCopy(SourceLocation InitLoc, - SourceLocation EqualLoc) { - return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc); + SourceLocation EqualLoc, + bool AllowExplicitConvs = false) { + return InitializationKind(IK_Copy, + AllowExplicitConvs? IC_ExplicitConvs : IC_Normal, + InitLoc, EqualLoc, EqualLoc); } /// \brief Create a default initialization. static InitializationKind CreateDefault(SourceLocation InitLoc) { - return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc); + return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc); } /// \brief Create a value initialization. @@ -409,46 +460,39 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc, bool isImplicit = false) { - return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, + return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal, InitLoc, LParenLoc, RParenLoc); } /// \brief Determine the initialization kind. InitKind getKind() const { - if (Kind > SIK_ImplicitValue) - return IK_Direct; - if (Kind == SIK_ImplicitValue) - return IK_Value; - - return (InitKind)Kind; + return Kind; } /// \brief Determine whether this initialization is an explicit cast. bool isExplicitCast() const { - return Kind == SIK_DirectCast || - Kind == SIK_DirectCStyleCast || - Kind == SIK_DirectFunctionalCast; + return Context >= IC_StaticCast; } /// \brief Determine whether this initialization is a C-style cast. bool isCStyleOrFunctionalCast() const { - return Kind == SIK_DirectCStyleCast || Kind == SIK_DirectFunctionalCast; + return Context >= IC_CStyleCast; } - /// brief Determine whether this is a C-style cast. + /// \brief Determine whether this is a C-style cast. bool isCStyleCast() const { - return Kind == SIK_DirectCStyleCast; + return Context == IC_CStyleCast; } - /// brief Determine whether this is a functional-style cast. + /// \brief Determine whether this is a functional-style cast. bool isFunctionalCast() const { - return Kind == SIK_DirectFunctionalCast; + return Context == IC_FunctionalCast; } /// \brief Determine whether this initialization is an implicit /// value-initialization, e.g., as occurs during aggregate /// initialization. - bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; } + bool isImplicitValueInit() const { return Context == IC_Implicit; } /// \brief Retrieve the location at which initialization is occurring. SourceLocation getLocation() const { return Locations[0]; } @@ -461,16 +505,26 @@ public: /// \brief Retrieve the location of the equal sign for copy initialization /// (if present). SourceLocation getEqualLoc() const { - assert(Kind == SIK_Copy && "Only copy initialization has an '='"); + assert(Kind == IK_Copy && "Only copy initialization has an '='"); return Locations[1]; } - - bool isCopyInit() const { return Kind == SIK_Copy; } + + bool isCopyInit() const { return Kind == IK_Copy; } + + /// \brief Retrieve whether this initialization allows the use of explicit + /// constructors. + bool AllowExplicit() const { return !isCopyInit(); } + + /// \brief Retrieve whether this initialization allows the use of explicit + /// conversion functions. + bool allowExplicitConversionFunctions() const { + return !isCopyInit() || Context == IC_ExplicitConvs; + } /// \brief Retrieve the source range containing the locations of the open /// and closing parentheses for value and direct initializations. SourceRange getParenRange() const { - assert((getKind() == IK_Direct || Kind == SIK_Value) && + assert((Kind == IK_Direct || Kind == IK_Value) && "Only direct- and value-initialization have parentheses"); return SourceRange(Locations[1], Locations[2]); } @@ -530,6 +584,10 @@ public: SK_ListInitialization, /// \brief Perform list-initialization with a constructor. SK_ListConstructorCall, + /// \brief Unwrap the single-element initializer list for a reference. + SK_UnwrapInitList, + /// \brief Rewrap the single-element initializer list for a reference. + SK_RewrapInitList, /// \brief Perform initialization via a constructor. SK_ConstructorInitialization, /// \brief Zero-initialize the object @@ -544,12 +602,17 @@ public: /// \brief Array initialization (from an array rvalue). /// This is a GNU C extension. SK_ArrayInit, + /// \brief Array initialization from a parenthesized initializer list. + /// This is a GNU C++ extension. + SK_ParenthesizedArrayInit, /// \brief Pass an object by indirect copy-and-restore. SK_PassByIndirectCopyRestore, /// \brief Pass an object by indirect restore. SK_PassByIndirectRestore, /// \brief Produce an Objective-C object pointer. - SK_ProduceObjCObject + SK_ProduceObjCObject, + /// \brief Construct a std::initializer_list from an initializer list. + SK_StdInitializerList }; /// \brief A single step in the initialization sequence. @@ -579,8 +642,12 @@ public: } Function; /// \brief When Kind = SK_ConversionSequence, the implicit conversion - /// sequence + /// sequence. ImplicitConversionSequence *ICS; + + /// \brief When Kind = SK_RewrapInitList, the syntactic form of the + /// wrapping list. + InitListExpr *WrappingSyntacticList; }; void Destroy(); @@ -635,14 +702,26 @@ public: FK_InitListBadDestinationType, /// \brief Overloading for a user-defined conversion failed. FK_UserConversionOverloadFailed, - /// \brief Overloaded for initialization by constructor failed. + /// \brief Overloading for initialization by constructor failed. FK_ConstructorOverloadFailed, + /// \brief Overloading for list-initialization by constructor failed. + FK_ListConstructorOverloadFailed, /// \brief Default-initialization of a 'const' object. FK_DefaultInitOfConst, /// \brief Initialization of an incomplete type. FK_Incomplete, + /// \brief Variable-length array must not have an initializer. + FK_VariableLengthArrayHasInitializer, /// \brief List initialization failed at some point. - FK_ListInitializationFailed + FK_ListInitializationFailed, + /// \brief Initializer has a placeholder type which cannot be + /// resolved by initialization. + FK_PlaceholderType, + /// \brief Failed to initialize a std::initializer_list because copy + /// construction of some element failed. + FK_InitListElementCopyFailure, + /// \brief List-copy-initialization chose an explicit constructor. + FK_ExplicitConstructor }; private: @@ -655,6 +734,9 @@ private: /// \brief The candidate set created when initialization failed. OverloadCandidateSet FailedCandidateSet; + /// \brief The incomplete type that caused a failure. + QualType FailedIncompleteType; + /// \brief Prints a follow-up note that highlights the location of /// the initialized entity, if it's remote. void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity); @@ -763,8 +845,9 @@ public: /// \param Function the function to which the overloaded function reference /// resolves. void AddAddressOverloadResolutionStep(FunctionDecl *Function, - DeclAccessPair Found); - + DeclAccessPair Found, + bool HadMultipleCandidates); + /// \brief Add a new step in the initialization that performs a derived-to- /// base cast. /// @@ -801,8 +884,9 @@ public: /// a constructor or a conversion function. void AddUserConversionStep(FunctionDecl *Function, DeclAccessPair FoundDecl, - QualType T); - + QualType T, + bool HadMultipleCandidates); + /// \brief Add a new step that performs a qualification conversion to the /// given type. void AddQualificationConversionStep(QualType Ty, @@ -812,17 +896,23 @@ public: void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, QualType T); - /// \brief Add a list-initialiation step. + /// \brief Add a list-initialization step. void AddListInitializationStep(QualType T); /// \brief Add a constructor-initialization step. + /// + /// \arg FromInitList The constructor call is syntactically an initializer + /// list. + /// \arg AsInitList The constructor is called as an init list constructor. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, AccessSpecifier Access, - QualType T); + QualType T, + bool HadMultipleCandidates, + bool FromInitList, bool AsInitList); /// \brief Add a zero-initialization step. void AddZeroInitializationStep(QualType T); - + /// \brief Add a C assignment step. // // FIXME: It isn't clear whether this should ever be needed; @@ -840,6 +930,9 @@ public: /// \brief Add an array initialization step. void AddArrayInitStep(QualType T); + /// \brief Add a parenthesized array initialization step. + void AddParenthesizedArrayInitStep(QualType T); + /// \brief Add a step to pass an object by indirect copy-restore. void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy); @@ -847,10 +940,20 @@ public: /// retaining it). void AddProduceObjCObjectStep(QualType T); + /// \brief Add a step to construct a std::initializer_list object from an + /// initializer list. + void AddStdInitializerListConstructionStep(QualType T); + + /// \brief Add steps to unwrap a initializer list for a reference around a + /// single element and rewrap it at the end. + void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic); + /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; this->Failure = Failure; + assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) && + "Incomplete type failure requires a type!"); } /// \brief Note that this initialization sequence failed due to failed @@ -863,12 +966,19 @@ public: return FailedCandidateSet; } - /// brief Get the overloading result, for when the initialization + /// \brief Get the overloading result, for when the initialization /// sequence failed due to a bad overload. OverloadingResult getFailedOverloadResult() const { return FailedOverloadResult; } + /// \brief Note that this initialization sequence failed due to an + /// incomplete type. + void setIncompleteTypeFailure(QualType IncompleteType) { + FailedIncompleteType = IncompleteType; + SetFailed(FK_Incomplete); + } + /// \brief Determine why initialization failed. FailureKind getFailureKind() const { assert(Failed() && "Not an initialization failure!"); diff --git a/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h b/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h index e1d3ae9..93cb8cb 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h @@ -36,16 +36,16 @@ class LocInfoType : public Type { TypeSourceInfo *DeclInfo; LocInfoType(QualType ty, TypeSourceInfo *TInfo) - : Type((TypeClass)LocInfo, ty, ty->isDependentType(), + : Type((TypeClass)LocInfo, ty, ty->isDependentType(), ty->isInstantiationDependentType(), ty->isVariablyModifiedType(), - ty->containsUnexpandedParameterPack()), - DeclInfo(TInfo) { - assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?"); - } + ty->containsUnexpandedParameterPack()), + DeclInfo(TInfo) { + assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?"); + } friend class Sema; - public: +public: QualType getType() const { return getCanonicalTypeInternal(); } TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h index 6630bb2..fe5d262 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h @@ -214,6 +214,12 @@ public: return Redecl; } + /// \brief Determine whether this lookup is permitted to see hidden + /// declarations, such as those in modules that have not yet been imported. + bool isHiddenDeclarationVisible() const { + return Redecl || LookupKind == Sema::LookupTagName; + } + /// Sets whether tag declarations should be hidden by non-tag /// declarations during resolution. The default is true. void setHideTags(bool Hide) { @@ -266,23 +272,35 @@ public: return Paths; } - /// \brief Tests whether the given declaration is acceptable. - bool isAcceptableDecl(NamedDecl *D) const { - if (!D->isInIdentifierNamespace(IDNS)) - return false; - - // So long as this declaration is not module-private or was parsed as - // part of this translation unit (i.e., in the module), we're allowed to - // find it. - if (!D->isModulePrivate() || !D->isFromASTFile()) + /// \brief Determine whether the given declaration is visible to the + /// program. + static bool isVisible(NamedDecl *D) { + // If this declaration is not hidden, it's visible. + if (!D->isHidden()) return true; - + // FIXME: We should be allowed to refer to a module-private name from // within the same module, e.g., during template instantiation. // This requires us know which module a particular declaration came from. return false; } - + + /// \brief Retrieve the accepted (re)declaration of the given declaration, + /// if there is one. + NamedDecl *getAcceptableDecl(NamedDecl *D) const { + if (!D->isInIdentifierNamespace(IDNS)) + return 0; + + if (isHiddenDeclarationVisible() || isVisible(D)) + return D; + + return getAcceptableDeclSlow(D); + } + +private: + NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const; +public: + /// \brief Returns the identifier namespace mask for this lookup. unsigned getIdentifierNamespace() const { return IDNS; @@ -532,6 +550,11 @@ public: return *I++; } + /// Restart the iteration. + void restart() { + I = Results.begin(); + } + /// Erase the last element returned from this iterator. void erase() { Results.Decls.erase(--I); @@ -569,7 +592,7 @@ private: void diagnose() { if (isAmbiguous()) SemaRef.DiagnoseAmbiguousLookup(*this); - else if (isClassLookup() && SemaRef.getLangOptions().AccessControl) + else if (isClassLookup() && SemaRef.getLangOpts().AccessControl) SemaRef.CheckLookupAccess(*this); } @@ -582,7 +605,13 @@ private: void configure(); // Sanity checks. - void sanity() const; + void sanityImpl() const; + + void sanity() const { +#ifndef NDEBUG + sanityImpl(); +#endif + } bool sanityCheckUnresolved() const { for (iterator I = begin(), E = end(); I != E; ++I) diff --git a/contrib/llvm/tools/clang/include/clang/Sema/MultiInitializer.h b/contrib/llvm/tools/clang/include/clang/Sema/MultiInitializer.h deleted file mode 100644 index c44e393..0000000 --- a/contrib/llvm/tools/clang/include/clang/Sema/MultiInitializer.h +++ /dev/null @@ -1,72 +0,0 @@ -//===--- MultiInitializer.h - Initializer expression group ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the MultiInitializer class, which can represent a list -// initializer or a parentheses-wrapped group of expressions in a C++ member -// initializer. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_SEMA_MULTIINITIALIZER_H -#define LLVM_CLANG_SEMA_MULTIINITIALIZER_H - -#include "clang/Sema/Ownership.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/PointerUnion.h" - -namespace clang { - class ASTContext; - class Expr; - class InitializationKind; - class InitializedEntity; - class InitListExpr; - class Sema; - -class MultiInitializer { - llvm::PointerUnion<Expr*, Expr**> InitListOrExpressions; - unsigned NumInitializers; - SourceLocation LParenLoc; - SourceLocation RParenLoc; - - InitListExpr *getInitList() const; - Expr **getExpressions() const { return InitListOrExpressions.get<Expr**>(); } - -public: - MultiInitializer(Expr* InitList) - : InitListOrExpressions(InitList) - {} - - MultiInitializer(SourceLocation LParenLoc, Expr **Exprs, unsigned NumInits, - SourceLocation RParenLoc) - : InitListOrExpressions(Exprs), NumInitializers(NumInits), - LParenLoc(LParenLoc), RParenLoc(RParenLoc) - {} - - bool isInitializerList() const { return InitListOrExpressions.is<Expr*>(); } - - SourceLocation getStartLoc() const; - SourceLocation getEndLoc() const; - - typedef Expr **iterator; - iterator begin() const; - iterator end() const; - - bool isTypeDependent() const; - - bool DiagnoseUnexpandedParameterPack(Sema &SemaRef) const; - - // Return the InitListExpr or create a ParenListExpr. - Expr *CreateInitExpr(ASTContext &Ctx, QualType T) const; - - ExprResult PerformInit(Sema &SemaRef, InitializedEntity Entity, - InitializationKind Kind) const; -}; -} - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h index dbc0926..d334447 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h @@ -24,6 +24,7 @@ #include "clang/Sema/SemaFixItUtils.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" namespace clang { class ASTContext; @@ -111,6 +112,23 @@ namespace clang { ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind); + /// NarrowingKind - The kind of narrowing conversion being performed by a + /// standard conversion sequence according to C++11 [dcl.init.list]p7. + enum NarrowingKind { + /// Not a narrowing conversion. + NK_Not_Narrowing, + + /// A narrowing conversion by virtue of the source and destination types. + NK_Type_Narrowing, + + /// A narrowing conversion, because a constant expression got narrowed. + NK_Constant_Narrowing, + + /// A narrowing conversion, because a non-constant-expression variable might + /// have got narrowed. + NK_Variable_Narrowing + }; + /// StandardConversionSequence - represents a standard conversion /// sequence (C++ 13.3.3.1.1). A standard conversion sequence /// contains between zero and three conversions. If a particular @@ -217,6 +235,9 @@ namespace clang { } ImplicitConversionRank getRank() const; + NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted, + APValue &ConstantValue, + QualType &ConstantType) const; bool isPointerConversionToBool() const; bool isPointerConversionToVoidPointer(ASTContext& Context) const; void DebugPrint() const; @@ -225,9 +246,10 @@ namespace clang { /// UserDefinedConversionSequence - Represents a user-defined /// conversion sequence (C++ 13.3.3.1.2). struct UserDefinedConversionSequence { - /// Before - Represents the standard conversion that occurs before - /// the actual user-defined conversion. (C++ 13.3.3.1.2p1): + /// \brief Represents the standard conversion that occurs before + /// the actual user-defined conversion. /// + /// C++11 13.3.3.1.2p1: /// If the user-defined conversion is specified by a constructor /// (12.3.1), the initial standard conversion sequence converts /// the source type to the type required by the argument of the @@ -255,14 +277,15 @@ namespace clang { StandardConversionSequence After; /// ConversionFunction - The function that will perform the - /// user-defined conversion. + /// user-defined conversion. Null if the conversion is an + /// aggregate initialization from an initializer list. FunctionDecl* ConversionFunction; /// \brief The declaration that we found via name lookup, which might be /// the same as \c ConversionFunction or it might be a using declaration /// that refers to \c ConversionFunction. DeclAccessPair FoundConversionFunction; - + void DebugPrint() const; }; @@ -379,7 +402,14 @@ namespace clang { }; /// ConversionKind - The kind of implicit conversion sequence. - unsigned ConversionKind; + unsigned ConversionKind : 30; + + /// \brief Whether the argument is an initializer list. + bool ListInitializationSequence : 1; + + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool StdInitializerListElement : 1; void setKind(Kind K) { destruct(); @@ -409,12 +439,17 @@ namespace clang { BadConversionSequence Bad; }; - ImplicitConversionSequence() : ConversionKind(Uninitialized) {} + ImplicitConversionSequence() + : ConversionKind(Uninitialized), ListInitializationSequence(false), + StdInitializerListElement(false) + {} ~ImplicitConversionSequence() { destruct(); } ImplicitConversionSequence(const ImplicitConversionSequence &Other) - : ConversionKind(Other.ConversionKind) + : ConversionKind(Other.ConversionKind), + ListInitializationSequence(Other.ListInitializationSequence), + StdInitializerListElement(Other.StdInitializerListElement) { switch (ConversionKind) { case Uninitialized: break; @@ -461,7 +496,7 @@ namespace clang { return 3; } - return 3; + llvm_unreachable("Invalid ImplicitConversionSequence::Kind!"); } bool isBad() const { return getKind() == BadConversion; } @@ -499,6 +534,26 @@ namespace clang { Ambiguous.construct(); } + /// \brief Whether this sequence was created by the rules of + /// list-initialization sequences. + bool isListInitializationSequence() const { + return ListInitializationSequence; + } + + void setListInitializationSequence() { + ListInitializationSequence = true; + } + + /// \brief Whether the target is really a std::initializer_list, and the + /// sequence only represents the worst element conversion. + bool isStdInitializerListElement() const { + return StdInitializerListElement; + } + + void setStdInitializerListElement(bool V = true) { + StdInitializerListElement = V; + } + // The result of a comparison between implicit conversion // sequences. Use Sema::CompareImplicitConversionSequences to // actually perform the comparison. @@ -565,12 +620,17 @@ namespace clang { CXXConversionDecl *Surrogate; /// Conversions - The conversion sequences used to convert the - /// function arguments to the function parameters. - SmallVector<ImplicitConversionSequence, 4> Conversions; + /// function arguments to the function parameters, the pointer points to a + /// fixed size array with NumConversions elements. The memory is owned by + /// the OverloadCandidateSet. + ImplicitConversionSequence *Conversions; /// The FixIt hints which can be used to fix the Bad candidate. ConversionFixItGenerator Fix; + /// NumConversions - The number of elements in the Conversions array. + unsigned NumConversions; + /// Viable - True to indicate that this overload candidate is viable. bool Viable; @@ -639,10 +699,9 @@ namespace clang { /// hasAmbiguousConversion - Returns whether this overload /// candidate requires an ambiguous conversion or not. bool hasAmbiguousConversion() const { - for (SmallVectorImpl<ImplicitConversionSequence>::const_iterator - I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { - if (!I->isInitialized()) return false; - if (I->isAmbiguous()) return true; + for (unsigned i = 0, e = NumConversions; i != e; ++i) { + if (!Conversions[i].isInitialized()) return false; + if (Conversions[i].isAmbiguous()) return true; } return false; } @@ -663,17 +722,29 @@ namespace clang { /// OverloadCandidateSet - A set of overload candidates, used in C++ /// overload resolution (C++ 13.3). - class OverloadCandidateSet : public SmallVector<OverloadCandidate, 16> { - typedef SmallVector<OverloadCandidate, 16> inherited; + class OverloadCandidateSet { + SmallVector<OverloadCandidate, 16> Candidates; llvm::SmallPtrSet<Decl *, 16> Functions; - SourceLocation Loc; - + // Allocator for OverloadCandidate::Conversions. We store the first few + // elements inline to avoid allocation for small sets. + llvm::BumpPtrAllocator ConversionSequenceAllocator; + + SourceLocation Loc; + + unsigned NumInlineSequences; + char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; + OverloadCandidateSet(const OverloadCandidateSet &); OverloadCandidateSet &operator=(const OverloadCandidateSet &); public: - OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {} + OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} + ~OverloadCandidateSet() { + for (iterator i = begin(), e = end(); i != e; ++i) + for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) + i->Conversions[ii].~ImplicitConversionSequence(); + } SourceLocation getLocation() const { return Loc; } @@ -686,6 +757,40 @@ namespace clang { /// \brief Clear out all of the candidates. void clear(); + typedef SmallVector<OverloadCandidate, 16>::iterator iterator; + iterator begin() { return Candidates.begin(); } + iterator end() { return Candidates.end(); } + + size_t size() const { return Candidates.size(); } + bool empty() const { return Candidates.empty(); } + + /// \brief Add a new candidate with NumConversions conversion sequence slots + /// to the overload set. + OverloadCandidate &addCandidate(unsigned NumConversions = 0) { + Candidates.push_back(OverloadCandidate()); + OverloadCandidate &C = Candidates.back(); + + // Assign space from the inline array if there are enough free slots + // available. + if (NumConversions + NumInlineSequences <= 16) { + ImplicitConversionSequence *I = + (ImplicitConversionSequence*)InlineSpace; + C.Conversions = &I[NumInlineSequences]; + NumInlineSequences += NumConversions; + } else { + // Otherwise get memory from the allocator. + C.Conversions = ConversionSequenceAllocator + .Allocate<ImplicitConversionSequence>(NumConversions); + } + + // Construct the new objects. + for (unsigned i = 0; i != NumConversions; ++i) + new (&C.Conversions[i]) ImplicitConversionSequence(); + + C.NumConversions = NumConversions; + return C; + } + /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator& Best, @@ -693,7 +798,7 @@ namespace clang { void NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, const char *Opc = 0, SourceLocation Loc = SourceLocation()); }; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h index 735a26b..3ff0459 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h @@ -141,7 +141,11 @@ namespace clang { struct TemplateIdAnnotation { /// \brief The nested-name-specifier that precedes the template name. CXXScopeSpec SS; - + + /// TemplateKWLoc - The location of the template keyword within the + /// source. + SourceLocation TemplateKWLoc; + /// TemplateNameLoc - The location of the template name within the /// source. SourceLocation TemplateNameLoc; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h index a31312c..aa55705 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h @@ -33,9 +33,10 @@ class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry { Decl *TheDecl; SourceLocation Loc; const char *Message; - + public: - PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, const char *Msg) + PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, + const char *Msg) : S(S), TheDecl(D), Loc(Loc), Message(Msg) {} virtual void print(raw_ostream &OS) const; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h index cff8b33..e9aa173 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h @@ -57,7 +57,7 @@ public: /// BlockScope - This is a scope that corresponds to a block/closure object. /// Blocks serve as top-level scopes for some objects like labels, they /// also prevent things like break and continue. BlockScopes always have - /// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well. + /// the FnScope and DeclScope flags set as well. BlockScope = 0x40, /// TemplateParamScope - This is a scope that corresponds to the @@ -114,16 +114,12 @@ private: /// pointer is non-null and points to it. This is used for label processing. Scope *FnParent; - /// BreakParent/ContinueParent - This is a direct link to the immediately - /// preceding BreakParent/ContinueParent if this scope is not one, or null if - /// there is no containing break/continue scope. + /// BreakParent/ContinueParent - This is a direct link to the innermost + /// BreakScope/ContinueScope which contains the contents of this scope + /// for control flow purposes (and might be this scope itself), or null + /// if there is no such scope. Scope *BreakParent, *ContinueParent; - /// ControlParent - This is a direct link to the immediately - /// preceding ControlParent if this scope is not one, or null if - /// there is no containing control scope. - Scope *ControlParent; - /// BlockParent - This is a direct link to the immediately containing /// BlockScope if this scope is not one, or null if there is none. Scope *BlockParent; @@ -180,12 +176,9 @@ public: Scope *getFnParent() { return FnParent; } /// getContinueParent - Return the closest scope that a continue statement - /// would be affected by. If the closest scope is a closure scope, we know - /// that there is no loop *inside* the closure. + /// would be affected by. Scope *getContinueParent() { - if (ContinueParent && !ContinueParent->isBlockScope()) - return ContinueParent; - return 0; + return ContinueParent; } const Scope *getContinueParent() const { @@ -193,20 +186,14 @@ public: } /// getBreakParent - Return the closest scope that a break statement - /// would be affected by. If the closest scope is a block scope, we know - /// that there is no loop *inside* the block. + /// would be affected by. Scope *getBreakParent() { - if (BreakParent && !BreakParent->isBlockScope()) - return BreakParent; - return 0; + return BreakParent; } const Scope *getBreakParent() const { return const_cast<Scope*>(this)->getBreakParent(); } - Scope *getControlParent() { return ControlParent; } - const Scope *getControlParent() const { return ControlParent; } - Scope *getBlockParent() { return BlockParent; } const Scope *getBlockParent() const { return BlockParent; } @@ -310,6 +297,10 @@ public: /// \brief Determine whether this scope is a C++ 'try' block. bool isTryScope() const { return getFlags() & Scope::TryScope; } + /// containedInPrototypeScope - Return true if this or a parent scope + /// is a FunctionPrototypeScope. + bool containedInPrototypeScope() const; + typedef UsingDirectivesTy::iterator udir_iterator; typedef UsingDirectivesTy::const_iterator const_udir_iterator; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h index 9ef6d3c..ceaf586 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h @@ -18,19 +18,36 @@ #include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SetVector.h" namespace clang { class BlockDecl; +class CXXMethodDecl; class IdentifierInfo; class LabelDecl; class ReturnStmt; class Scope; class SwitchStmt; +class VarDecl; namespace sema { +/// \brief Contains information about the compound statement currently being +/// parsed. +class CompoundScopeInfo { +public: + CompoundScopeInfo() + : HasEmptyLoopBodies(false) { } + + /// \brief Whether this compound stamement contains `for' or `while' loops + /// with empty bodies. + bool HasEmptyLoopBodies; + + void setHasEmptyLoopBodies() { + HasEmptyLoopBodies = true; + } +}; + class PossiblyUnreachableDiag { public: PartialDiagnostic PD; @@ -45,11 +62,17 @@ public: /// \brief Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { +protected: + enum ScopeKind { + SK_Function, + SK_Block, + SK_Lambda + }; + public: - - /// \brief Whether this scope information structure defined information for - /// a block. - bool IsBlockInfo; + /// \brief What kind of scope we are describing. + /// + ScopeKind Kind; /// \brief Whether this function contains a VLA, @try, try, C++ /// initializer, or anything else that can't be jumped past. @@ -72,7 +95,11 @@ public: /// block, if there is any chance of applying the named return value /// optimization. SmallVector<ReturnStmt*, 4> Returns; - + + /// \brief The stack of currently active compound stamement scopes in the + /// function. + SmallVector<CompoundScopeInfo, 4> CompoundScopes; + /// \brief A list of PartialDiagnostics created but delayed within the /// current function scope. These diagnostics are vetted for reachability /// prior to being emitted. @@ -96,7 +123,7 @@ public: } FunctionScopeInfo(DiagnosticsEngine &Diag) - : IsBlockInfo(false), + : Kind(SK_Function), HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), @@ -111,8 +138,162 @@ public: static bool classof(const FunctionScopeInfo *FSI) { return true; } }; +class CapturingScopeInfo : public FunctionScopeInfo { +public: + enum ImplicitCaptureStyle { + ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block + }; + + ImplicitCaptureStyle ImpCaptureStyle; + + class Capture { + // There are two categories of capture: capturing 'this', and capturing + // local variables. There are three ways to capture a local variable: + // capture by copy in the C++11 sense, capture by reference + // in the C++11 sense, and __block capture. Lambdas explicitly specify + // capture by copy or capture by reference. For blocks, __block capture + // applies to variables with that annotation, variables of reference type + // are captured by reference, and other variables are captured by copy. + enum CaptureKind { + Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block + }; + + // The variable being captured (if we are not capturing 'this'), + // and misc bits descibing the capture. + llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind; + + // Expression to initialize a field of the given type, and whether this + // is a nested capture; the expression is only required if we are + // capturing ByVal and the variable's type has a non-trivial + // copy constructor. + llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested; + + /// \brief The source location at which the first capture occurred.. + SourceLocation Loc; + + /// \brief The location of the ellipsis that expands a parameter pack. + SourceLocation EllipsisLoc; + + /// \brief The type as it was captured, which is in effect the type of the + /// non-static data member that would hold the capture. + QualType CaptureType; + + public: + Capture(VarDecl *Var, bool block, bool byRef, bool isNested, + SourceLocation Loc, SourceLocation EllipsisLoc, + QualType CaptureType, Expr *Cpy) + : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy), + CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc), + CaptureType(CaptureType){} + + enum IsThisCapture { ThisCapture }; + Capture(IsThisCapture, bool isNested, SourceLocation Loc, + QualType CaptureType, Expr *Cpy) + : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc), + EllipsisLoc(), CaptureType(CaptureType) { } + + bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } + bool isVariableCapture() const { return !isThisCapture(); } + bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; } + bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } + bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; } + bool isNested() { return CopyExprAndNested.getInt(); } + + VarDecl *getVariable() const { + return VarAndKind.getPointer(); + } + + /// \brief Retrieve the location at which this variable was captured. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the source location of the ellipsis, whose presence + /// indicates that the capture is a pack expansion. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + + /// \brief Retrieve the capture type for this capture, which is effectively + /// the type of the non-static data member in the lambda/block structure + /// that would store this capture. + QualType getCaptureType() const { return CaptureType; } + + Expr *getCopyExpr() const { + return CopyExprAndNested.getPointer(); + } + }; + + CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) + : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), + HasImplicitReturnType(false) + {} + + /// CaptureMap - A map of captured variables to (index+1) into Captures. + llvm::DenseMap<VarDecl*, unsigned> CaptureMap; + + /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; + /// zero if 'this' is not captured. + unsigned CXXThisCaptureIndex; + + /// Captures - The captures. + SmallVector<Capture, 4> Captures; + + /// \brief - Whether the target type of return statements in this context + /// is deduced (e.g. a lambda or block with omitted return type). + bool HasImplicitReturnType; + + /// ReturnType - The target type of return statements in this context, + /// or null if unknown. + QualType ReturnType; + + void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, + SourceLocation Loc, SourceLocation EllipsisLoc, + QualType CaptureType, Expr *Cpy) { + Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, + EllipsisLoc, CaptureType, Cpy)); + CaptureMap[Var] = Captures.size(); + } + + void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, + Expr *Cpy) { + Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, + Cpy)); + CXXThisCaptureIndex = Captures.size(); + } + + /// \brief Determine whether the C++ 'this' is captured. + bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } + + /// \brief Retrieve the capture of C++ 'this', if it has been captured. + Capture &getCXXThisCapture() { + assert(isCXXThisCaptured() && "this has not been captured"); + return Captures[CXXThisCaptureIndex - 1]; + } + + /// \brief Determine whether the given variable has been captured. + bool isCaptured(VarDecl *Var) const { + return CaptureMap.count(Var); + } + + /// \brief Retrieve the capture of the given variable, if it has been + /// captured already. + Capture &getCapture(VarDecl *Var) { + assert(isCaptured(Var) && "Variable has not been captured"); + return Captures[CaptureMap[Var] - 1]; + } + + const Capture &getCapture(VarDecl *Var) const { + llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known + = CaptureMap.find(Var); + assert(Known != CaptureMap.end() && "Variable has not been captured"); + return Captures[Known->second - 1]; + } + + static bool classof(const FunctionScopeInfo *FSI) { + return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; + } + static bool classof(const CapturingScopeInfo *BSI) { return true; } +}; + /// \brief Retains information about a block that is currently being parsed. -class BlockScopeInfo : public FunctionScopeInfo { +class BlockScopeInfo : public CapturingScopeInfo { public: BlockDecl *TheDecl; @@ -120,36 +301,79 @@ public: /// arguments etc. Scope *TheScope; - /// ReturnType - The return type of the block, or null if the block - /// signature didn't provide an explicit return type. - QualType ReturnType; - /// BlockType - The function type of the block, if one was given. /// Its return type may be BuiltinType::Dependent. QualType FunctionType; - /// CaptureMap - A map of captured variables to (index+1) into Captures. - llvm::DenseMap<VarDecl*, unsigned> CaptureMap; - - /// Captures - The captured variables. - SmallVector<BlockDecl::Capture, 4> Captures; - - /// CapturesCXXThis - Whether this block captures 'this'. - bool CapturesCXXThis; - BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) - : FunctionScopeInfo(Diag), TheDecl(Block), TheScope(BlockScope), - CapturesCXXThis(false) + : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), + TheScope(BlockScope) { - IsBlockInfo = true; + Kind = SK_Block; } virtual ~BlockScopeInfo(); - static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; } + static bool classof(const FunctionScopeInfo *FSI) { + return FSI->Kind == SK_Block; + } static bool classof(const BlockScopeInfo *BSI) { return true; } }; +class LambdaScopeInfo : public CapturingScopeInfo { +public: + /// \brief The class that describes the lambda. + CXXRecordDecl *Lambda; + + /// \brief The class that describes the lambda. + CXXMethodDecl *CallOperator; + + /// \brief Source range covering the lambda introducer [...]. + SourceRange IntroducerRange; + + /// \brief The number of captures in the \c Captures list that are + /// explicit captures. + unsigned NumExplicitCaptures; + + /// \brief Whether this is a mutable lambda. + bool Mutable; + + /// \brief Whether the (empty) parameter list is explicit. + bool ExplicitParams; + + /// \brief Whether any of the capture expressions requires cleanups. + bool ExprNeedsCleanups; + + /// \brief Variables used to index into by-copy array captures. + llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; + + /// \brief Offsets into the ArrayIndexVars array at which each capture starts + /// its list of array index variables. + llvm::SmallVector<unsigned, 4> ArrayIndexStarts; + + LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, + CXXMethodDecl *CallOperator) + : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), + CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), + ExprNeedsCleanups(false) + { + Kind = SK_Lambda; + } + + virtual ~LambdaScopeInfo(); + + /// \brief Note when + void finishedExplicitCaptures() { + NumExplicitCaptures = Captures.size(); + } + + static bool classof(const FunctionScopeInfo *FSI) { + return FSI->Kind == SK_Lambda; + } + static bool classof(const LambdaScopeInfo *BSI) { return true; } + +}; + } } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h index 22d5db2..31c410a 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h @@ -22,13 +22,15 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/LocInfoType.h" -#include "clang/Sema/MultiInitializer.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/NSAPI.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" @@ -44,6 +46,7 @@ namespace llvm { class APSInt; template <typename ValueT> struct DenseMapInfo; template <typename ValueT, typename ValueInfoT> class DenseSet; + class SmallBitVector; } namespace clang { @@ -58,6 +61,7 @@ namespace clang { class BlockDecl; class CXXBasePath; class CXXBasePaths; + class CXXBindTemporaryExpr; typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; class CXXConstructorDecl; class CXXConversionDecl; @@ -74,6 +78,7 @@ namespace clang { class ClassTemplateSpecializationDecl; class CodeCompleteConsumer; class CodeCompletionAllocator; + class CodeCompletionTUInfo; class CodeCompletionResult; class Decl; class DeclAccessPair; @@ -100,6 +105,7 @@ namespace clang { class InitializedEntity; class IntegerLiteral; class LabelStmt; + class LambdaExpr; class LangOptions; class LocalInstantiationScope; class LookupResult; @@ -126,6 +132,7 @@ namespace clang { class ParmVarDecl; class Preprocessor; class PseudoDestructorTypeStorage; + class PseudoObjectExpr; class QualType; class StandardConversionSequence; class Stmt; @@ -156,12 +163,15 @@ namespace clang { class VisibilityAttr; class VisibleDeclConsumer; class IndirectFieldDecl; - + namespace sema { class AccessedEntity; class BlockScopeInfo; + class CompoundScopeInfo; class DelayedDiagnostic; class FunctionScopeInfo; + class LambdaScopeInfo; + class PossiblyUnreachableDiag; class TemplateDeductionInfo; } @@ -213,7 +223,7 @@ public: /// PackContext - Manages the stack for #pragma pack. An alignment /// of 0 indicates default alignment. void *PackContext; // Really a "PragmaPackStack*" - + bool MSStructPragmaOn; // True when #pragma ms_struct on /// VisContext - Manages the stack for #pragma GCC visibility. @@ -223,6 +233,13 @@ public: /// requires cleanups to be run at its conclusion. bool ExprNeedsCleanups; + /// ExprCleanupObjects - This is the stack of objects requiring + /// cleanup that are created by the current full expression. The + /// element type here is ExprWithCleanups::Object. + SmallVector<BlockDecl*, 8> ExprCleanupObjects; + + llvm::SmallPtrSet<Expr*, 8> MaybeODRUseExprs; + /// \brief Stack containing information about each of the nested /// function, block, and method scopes that are currently active. /// @@ -231,11 +248,7 @@ public: /// that's used to parse every top-level function. SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes; - /// ExprTemporaries - This is the stack of temporaries that are created by - /// the current full expression. - SmallVector<CXXTemporary*, 8> ExprTemporaries; - - typedef LazyVector<TypedefNameDecl *, ExternalSemaSource, + typedef LazyVector<TypedefNameDecl *, ExternalSemaSource, &ExternalSemaSource::ReadExtVectorDecls, 2, 2> ExtVectorDeclsType; @@ -244,15 +257,21 @@ public: /// This is only necessary for issuing pretty diagnostics. ExtVectorDeclsType ExtVectorDecls; + /// \brief The set of types for which we have already complained about the + /// definitions being hidden. + /// + /// This set is used to suppress redundant diagnostics. + llvm::SmallPtrSet<NamedDecl *, 4> HiddenDefinitions; + /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. - llvm::OwningPtr<CXXFieldCollector> FieldCollector; + OwningPtr<CXXFieldCollector> FieldCollector; typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy; /// PureVirtualClassDiagSet - a set of class declarations which we have /// emitted a list of pure virtual functions. Used to prevent emitting the /// same list more than once. - llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; + OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; /// ParsingInitForAutoVars - a set of declarations with auto types for which /// we are currently parsing the initializer. @@ -284,27 +303,27 @@ public: /// we find this declaration of "foo" and complain that it is /// not visible. llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls; - + /// \brief Look for a locally scoped external declaration by the given name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator findLocallyScopedExternalDecl(DeclarationName Name); - - typedef LazyVector<VarDecl *, ExternalSemaSource, + + typedef LazyVector<VarDecl *, ExternalSemaSource, &ExternalSemaSource::ReadTentativeDefinitions, 2, 2> TentativeDefinitionsType; /// \brief All the tentative definitions encountered in the TU. TentativeDefinitionsType TentativeDefinitions; - typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource, + typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource, &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2> UnusedFileScopedDeclsType; - + /// \brief The set of file scoped decls seen so far that have not been used /// and must warn if not used. Only contains the first declaration. UnusedFileScopedDeclsType UnusedFileScopedDecls; - typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource, + typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource, &ExternalSemaSource::ReadDelegatingConstructors, 2, 2> DelegatingCtorDeclsType; @@ -322,11 +341,11 @@ public: /// \brief Callback to the parser to parse templated functions when needed. typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD); LateTemplateParserCB *LateTemplateParser; - void *OpaqueParser; + void *OpaqueParser; void SetLateTemplateParser(LateTemplateParserCB *LTP, void *P) { LateTemplateParser = LTP; - OpaqueParser = P; + OpaqueParser = P; } class DelayedDiagnostics; @@ -418,7 +437,7 @@ public: assert(ParsingDepth == 0); ActiveStackBase = state.SavedActiveStackBase; ParsingDepth = state.SavedParsingDepth; - } + } } DelayedDiagnostics; /// A RAII object to temporarily push a declaration context. @@ -427,11 +446,11 @@ public: Sema &S; DeclContext *SavedContext; ProcessingContextState SavedContextState; - + public: ContextRAII(Sema &S, DeclContext *ContextToPush) - : S(S), SavedContext(S.CurContext), - SavedContextState(S.DelayedDiagnostics.pushContext()) + : S(S), SavedContext(S.CurContext), + SavedContextState(S.DelayedDiagnostics.pushContext()) { assert(ContextToPush && "pushing null context"); S.CurContext = ContextToPush; @@ -454,9 +473,16 @@ public: /// identifier, declared or undeclared llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers; + /// ExtnameUndeclaredIdentifiers - Identifiers contained in + /// #pragma redefine_extname before declared. Used in Solaris system headers + /// to define functions that occur in multiple standards to call the version + /// in the currently selected standard. + llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers; + + /// \brief Load weak undeclared identifiers from the external source. void LoadExternalWeakUndeclaredIdentifiers(); - + /// WeakTopLevelDecl - Translation-unit scoped declarations generated by /// #pragma weak during processing of other Decls. /// I couldn't figure out a clean way to generate these in-line, so @@ -478,17 +504,44 @@ public: /// standard library. LazyDeclPtr StdBadAlloc; + /// \brief The C++ "std::initializer_list" template, which is defined in + /// <initializer_list>. + ClassTemplateDecl *StdInitializerList; + /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>. RecordDecl *CXXTypeInfoDecl; - + /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files. RecordDecl *MSVCGuidDecl; + /// \brief Caches identifiers/selectors for NSFoundation APIs. + llvm::OwningPtr<NSAPI> NSAPIObj; + + /// \brief The declaration of the Objective-C NSNumber class. + ObjCInterfaceDecl *NSNumberDecl; + + /// \brief The Objective-C NSNumber methods used to create NSNumber literals. + ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; + + /// \brief The declaration of the Objective-C NSArray class. + ObjCInterfaceDecl *NSArrayDecl; + + /// \brief The declaration of the arrayWithObjects:count: method. + ObjCMethodDecl *ArrayWithObjectsMethod; + + /// \brief The declaration of the Objective-C NSDictionary class. + ObjCInterfaceDecl *NSDictionaryDecl; + + /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method. + ObjCMethodDecl *DictionaryWithObjectsMethod; + + /// \brief id<NSCopying> type. + QualType QIDNSCopying; + /// A flag to remember whether the implicit forms of operator new and delete /// have been declared. bool GlobalNewDeleteDeclared; - /// A flag that is set when parsing a -dealloc method and no [super dealloc] /// call was found yet. bool ObjCShouldCallSuperDealloc; @@ -496,37 +549,26 @@ public: /// call was found yet. bool ObjCShouldCallSuperFinalize; - /// \brief The set of declarations that have been referenced within - /// a potentially evaluated expression. - typedef SmallVector<std::pair<SourceLocation, Decl *>, 10> - PotentiallyReferencedDecls; - - /// \brief A set of diagnostics that may be emitted. - typedef SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10> - PotentiallyEmittedDiagnostics; - /// \brief Describes how the expressions currently being parsed are /// evaluated at run-time, if at all. enum ExpressionEvaluationContext { /// \brief The current expression and its subexpressions occur within an - /// unevaluated operand (C++0x [expr]p8), such as a constant expression - /// or the subexpression of \c sizeof, where the type or the value of the - /// expression may be significant but no code will be generated to evaluate - /// the value of the expression at run time. + /// unevaluated operand (C++11 [expr]p7), such as the subexpression of + /// \c sizeof, where the type of the expression may be significant but + /// no code will be generated to evaluate the value of the expression at + /// run time. Unevaluated, + /// \brief The current context is "potentially evaluated" in C++11 terms, + /// but the expression is evaluated at compile-time (like the values of + /// cases in a switch statment). + ConstantEvaluated, + /// \brief The current expression is potentially evaluated at run time, /// which means that code may be generated to evaluate the value of the /// expression at run time. PotentiallyEvaluated, - /// \brief The current expression may be potentially evaluated or it may - /// be unevaluated, but it is impossible to tell from the lexical context. - /// This evaluation context is used primary for the operand of the C++ - /// \c typeid expression, whose argument is potentially evaluated only when - /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2). - PotentiallyPotentiallyEvaluated, - /// \brief The current expression is potentially evaluated, but any /// declarations referenced inside that expression are only used if /// in fact the current expression is used. @@ -547,47 +589,58 @@ public: /// \brief Whether the enclosing context needed a cleanup. bool ParentNeedsCleanups; - /// \brief The number of temporaries that were active when we - /// entered this expression evaluation context. - unsigned NumTemporaries; + /// \brief Whether we are in a decltype expression. + bool IsDecltype; + + /// \brief The number of active cleanup objects when we entered + /// this expression evaluation context. + unsigned NumCleanupObjects; - /// \brief The set of declarations referenced within a - /// potentially potentially-evaluated context. + llvm::SmallPtrSet<Expr*, 8> SavedMaybeODRUseExprs; + + /// \brief The lambdas that are present within this context, if it + /// is indeed an unevaluated context. + llvm::SmallVector<LambdaExpr *, 2> Lambdas; + + /// \brief The declaration that provides context for the lambda expression + /// if the normal declaration context does not suffice, e.g., in a + /// default function argument. + Decl *LambdaContextDecl; + + /// \brief The context information used to mangle lambda expressions + /// within this context. /// - /// When leaving a potentially potentially-evaluated context, each - /// of these elements will be as referenced if the corresponding - /// potentially potentially evaluated expression is potentially - /// evaluated. - PotentiallyReferencedDecls *PotentiallyReferenced; + /// This mangling information is allocated lazily, since most contexts + /// do not have lambda expressions. + LambdaMangleContext *LambdaMangle; - /// \brief The set of diagnostics to emit should this potentially - /// potentially-evaluated context become evaluated. - PotentiallyEmittedDiagnostics *PotentiallyDiagnosed; + /// \brief If we are processing a decltype type, a set of call expressions + /// for which we have deferred checking the completeness of the return type. + llvm::SmallVector<CallExpr*, 8> DelayedDecltypeCalls; + /// \brief If we are processing a decltype type, a set of temporary binding + /// expressions for which we have deferred checking the destructor. + llvm::SmallVector<CXXBindTemporaryExpr*, 8> DelayedDecltypeBinds; + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, - unsigned NumTemporaries, - bool ParentNeedsCleanups) + unsigned NumCleanupObjects, + bool ParentNeedsCleanups, + Decl *LambdaContextDecl, + bool IsDecltype) : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), - NumTemporaries(NumTemporaries), - PotentiallyReferenced(0), PotentiallyDiagnosed(0) { } - - void addReferencedDecl(SourceLocation Loc, Decl *Decl) { - if (!PotentiallyReferenced) - PotentiallyReferenced = new PotentiallyReferencedDecls; - PotentiallyReferenced->push_back(std::make_pair(Loc, Decl)); - } - - void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) { - if (!PotentiallyDiagnosed) - PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics; - PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD)); + IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), + LambdaContextDecl(LambdaContextDecl), LambdaMangle() { } + + ~ExpressionEvaluationContextRecord() { + delete LambdaMangle; } - - void Destroy() { - delete PotentiallyReferenced; - delete PotentiallyDiagnosed; - PotentiallyReferenced = 0; - PotentiallyDiagnosed = 0; + + /// \brief Retrieve the mangling context for lambdas. + LambdaMangleContext &getLambdaMangleContext() { + assert(LambdaContextDecl && "Need to have a lambda context declaration"); + if (!LambdaMangle) + LambdaMangle = new LambdaMangleContext; + return *LambdaMangle; } }; @@ -608,7 +661,17 @@ public: /// This is used for determining parameter types of other objects and is /// utterly meaningless on other types of special members. class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode { + public: + enum Kind { + NoMemberOrDeleted, + Ambiguous, + SuccessNonConst, + SuccessConst + }; + + private: llvm::PointerIntPair<CXXMethodDecl*, 2> Pair; + public: SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID) : FastFoldingSetNode(ID) @@ -617,15 +680,11 @@ public: CXXMethodDecl *getMethod() const { return Pair.getPointer(); } void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } - bool hasSuccess() const { return Pair.getInt() & 0x1; } - void setSuccess(bool B) { - Pair.setInt(unsigned(B) | hasConstParamMatch() << 1); - } + Kind getKind() const { return static_cast<Kind>(Pair.getInt()); } + void setKind(Kind K) { Pair.setInt(K); } - bool hasConstParamMatch() const { return Pair.getInt() & 0x2; } - void setConstParamMatch(bool B) { - Pair.setInt(B << 1 | unsigned(hasSuccess())); - } + bool hasSuccess() const { return getKind() >= SuccessNonConst; } + bool hasConstParamMatch() const { return getKind() == SuccessConst; } }; /// \brief A cache of special member function overload resolution results @@ -648,16 +707,16 @@ public: typedef llvm::DenseMap<ParmVarDecl *, SmallVector<ParmVarDecl *, 1> > UnparsedDefaultArgInstantiationsMap; - + /// \brief A mapping from parameters with unparsed default arguments to the /// set of instantiations of each parameter. /// /// This mapping is a temporary data structure used when parsing /// nested class templates or nested classes of class templates, /// where we might end up instantiating an inner class before the - /// default arguments of its methods have been parsed. + /// default arguments of its methods have been parsed. UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations; - + // Contains the locations of the beginning of unparsed default // argument locations. llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs; @@ -675,25 +734,31 @@ public: /// of selectors are "overloaded"). GlobalMethodPool MethodPool; - /// Method selectors used in a @selector expression. Used for implementation + /// Method selectors used in a @selector expression. Used for implementation /// of -Wselector. llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; - GlobalMethodPool::iterator ReadMethodPool(Selector Sel); + void ReadMethodPool(Selector Sel); /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); + + /// \brief Cause the active diagnostic on the DiagosticsEngine to be + /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and + /// should not be used elsewhere. + void EmitCurrentDiagnostic(unsigned DiagID); + public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind = TU_Complete, CodeCompleteConsumer *CompletionConsumer = 0); ~Sema(); - + /// \brief Perform initialization that occurs after the parser has been /// initialized but before it parses anything. void Initialize(); - - const LangOptions &getLangOptions() const { return LangOpts; } + + const LangOptions &getLangOpts() const { return LangOpts; } OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } FPOptions &getFPOptions() { return FPFeatures; } @@ -724,14 +789,32 @@ public: SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { } - explicit SemaDiagnosticBuilder(Sema &SemaRef) - : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { } - - ~SemaDiagnosticBuilder(); + ~SemaDiagnosticBuilder() { + // If we aren't active, there is nothing to do. + if (!isActive()) return; + + // Otherwise, we need to emit the diagnostic. First flush the underlying + // DiagnosticBuilder data, and clear the diagnostic builder itself so it + // won't emit the diagnostic in its own destructor. + // + // This seems wasteful, in that as written the DiagnosticBuilder dtor will + // do its own needless checks to see if the diagnostic needs to be + // emitted. However, because we take care to ensure that the builder + // objects never escape, a sufficiently smart compiler will be able to + // eliminate that code. + FlushCounts(); + Clear(); + + // Dispatch to Sema to emit the diagnostic. + SemaRef.EmitCurrentDiagnostic(DiagID); + } }; /// \brief Emit a diagnostic. - SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + DiagnosticBuilder DB = Diags.Report(Loc, DiagID); + return SemaDiagnosticBuilder(DB, *this, DiagID); + } /// \brief Emit a partial diagnostic. SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD); @@ -741,6 +824,9 @@ public: bool findMacroSpelling(SourceLocation &loc, StringRef name); + /// \brief Get a string to suggest for zero-initialization of a type. + const char *getFixItZeroInitializerForType(QualType T) const; + ExprResult Owned(Expr* E) { return E; } ExprResult Owned(ExprResult R) { return R; } StmtResult Owned(Stmt* S) { return S; } @@ -753,18 +839,27 @@ public: void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0, - const Decl *D = 0, const BlockExpr *blkExpr = 0); + void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator); + void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0, + const Decl *D = 0, const BlockExpr *blkExpr = 0); sema::FunctionScopeInfo *getCurFunction() const { return FunctionScopes.back(); } + void PushCompoundScope(); + void PopCompoundScope(); + + sema::CompoundScopeInfo &getCurCompoundScope() const; + bool hasAnyUnrecoverableErrorsInThisFunction() const; /// \brief Retrieve the current block, if any. sema::BlockScopeInfo *getCurBlock(); + /// \brief Retrieve the current lambda expression, if any. + sema::LambdaScopeInfo *getCurLambda(); + /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; } @@ -787,8 +882,8 @@ public: SourceLocation AttrLoc); QualType BuildFunctionType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, - bool Variadic, unsigned Quals, - RefQualifierKind RefQualifier, + bool Variadic, bool HasTrailingReturn, + unsigned Quals, RefQualifierKind RefQualifier, SourceLocation Loc, DeclarationName Entity, FunctionType::ExtInfo Info); QualType BuildMemberPointerType(QualType T, QualType Class, @@ -831,11 +926,11 @@ public: const FunctionProtoType *Source, SourceLocation SourceLoc); TypeResult ActOnTypeName(Scope *S, Declarator &D); - + /// \brief The parser has parsed the context-sensitive type 'instancetype' /// in an Objective-C message declaration. Return the appropriate type. ParsedType ActOnObjCInstanceType(SourceLocation Loc); - + bool RequireCompleteType(SourceLocation Loc, QualType T, const PartialDiagnostic &PD, std::pair<SourceLocation, PartialDiagnostic> Note); @@ -848,8 +943,7 @@ public: PartialDiagnostic> Note); bool RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - bool AllowIncompleteType = false); + const PartialDiagnostic &PD); QualType getElaboratedType(ElaboratedTypeKeyword Keyword, const CXXScopeSpec &SS, QualType T); @@ -864,6 +958,17 @@ public: // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // + /// List of decls defined in a function prototype. This contains EnumConstants + /// that incorrectly end up in translation unit scope because there is no + /// function to pin them on. ActOnFunctionDeclarator reads this list and patches + /// them into the FunctionDecl. + std::vector<NamedDecl*> DeclsInPrototypeScope; + /// Nonzero if we are currently parsing a function declarator. This is a counter + /// as opposed to a boolean so we can deal with nested function declarators + /// such as: + /// void f(void (*g)(), ...) + unsigned InFunctionDeclarator; + DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = 0); void DiagnoseUseOfUnimplementedSelectors(); @@ -873,6 +978,7 @@ public: bool isClassName = false, bool HasTrailingDot = false, ParsedType ObjectType = ParsedType(), + bool IsCtorOrDtorName = false, bool WantNontrivialTypeSourceInfo = false, IdentifierInfo **CorrectedII = 0); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); @@ -895,36 +1001,36 @@ public: NC_TypeTemplate, NC_FunctionTemplate }; - + class NameClassification { NameClassificationKind Kind; ExprResult Expr; TemplateName Template; ParsedType Type; const IdentifierInfo *Keyword; - + explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} - + public: NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {} - + NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} - - NameClassification(const IdentifierInfo *Keyword) + + NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword), Keyword(Keyword) { } - - static NameClassification Error() { - return NameClassification(NC_Error); + + static NameClassification Error() { + return NameClassification(NC_Error); } - - static NameClassification Unknown() { - return NameClassification(NC_Unknown); + + static NameClassification Unknown() { + return NameClassification(NC_Unknown); } - + static NameClassification NestedNameSpecifier() { return NameClassification(NC_NestedNameSpecifier); } - + static NameClassification TypeTemplate(TemplateName Name) { NameClassification Result(NC_TypeTemplate); Result.Template = Name; @@ -936,19 +1042,19 @@ public: Result.Template = Name; return Result; } - + NameClassificationKind getKind() const { return Kind; } - + ParsedType getType() const { assert(Kind == NC_Type); return Type; } - + ExprResult getExpression() const { assert(Kind == NC_Expression); return Expr; } - + TemplateName getTemplateName() const { assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); return Template; @@ -959,7 +1065,7 @@ public: return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template; } }; - + /// \brief Perform name lookup on the given name, classifying it based on /// the results of name lookup and the following token. /// @@ -976,14 +1082,14 @@ public: /// /// \param NameLoc The location of the identifier. /// - /// \param NextToken The token following the identifier. Used to help + /// \param NextToken The token following the identifier. Used to help /// disambiguate the name. NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, const Token &NextToken); - + Decl *ActOnDeclarator(Scope *S, Declarator &D); Decl *HandleDeclarator(Scope *S, Declarator &D, @@ -992,6 +1098,9 @@ public: const LookupResult &Previous, Scope *S); bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); + bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, + DeclarationName Name, + SourceLocation Loc); void DiagnoseFunctionSpecifiers(Declarator& D); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); @@ -1009,6 +1118,8 @@ public: // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckCompleteVariableDeclaration(VarDecl *var); + void ActOnStartFunctionDeclarator(); + void ActOnEndFunctionDeclarator(); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -1016,20 +1127,7 @@ public: bool &AddToScope); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); - /// \brief The kind of constexpr declaration checking we are performing. - /// - /// The kind affects which diagnostics (if any) are emitted if the function - /// does not satisfy the requirements of a constexpr function declaration. - enum CheckConstexprKind { - /// \brief Check a constexpr function declaration, and produce errors if it - /// does not satisfy the requirements. - CCK_Declaration, - /// \brief Check a constexpr function template instantiation. - CCK_Instantiation, - /// \brief Produce notes explaining why an instantiation was not constexpr. - CCK_NoteNonConstexprInstantiation - }; - bool CheckConstexprFunctionDecl(const FunctionDecl *FD, CheckConstexprKind CCK); + bool CheckConstexprFunctionDecl(const FunctionDecl *FD); bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body); void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); @@ -1105,23 +1203,22 @@ public: /// \brief The parser has processed a module import declaration. /// - /// \param ImportLoc The location of the '__import_module__' keyword. + /// \param AtLoc The location of the '@' symbol, if any. /// - /// \param ModuleName The name of the module. + /// \param ImportLoc The location of the 'import' keyword. /// - /// \param ModuleNameLoc The location of the module name. - DeclResult ActOnModuleImport(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc); - - /// \brief Diagnose that \p New is a module-private redeclaration of - /// \p Old. - void diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old, - SourceLocation ModulePrivateKeyword - = SourceLocation()); - + /// \param Path The module access path. + DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, + ModuleIdPath Path); + /// \brief Retrieve a suitable printing policy. - PrintingPolicy getPrintingPolicy() const; + PrintingPolicy getPrintingPolicy() const { + return getPrintingPolicy(Context, PP); + } + + /// \brief Retrieve a suitable printing policy. + static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx, + const Preprocessor &PP); /// Scope actions. void ActOnPopScope(SourceLocation Loc, Scope *S); @@ -1132,14 +1229,12 @@ public: Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, MultiTemplateParamsArg TemplateParams); - - StmtResult ActOnVlaStmt(const DeclSpec &DS); Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, RecordDecl *Record); - Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, + Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record); bool isAcceptableTagRedeclaration(const TagDecl *Previous, @@ -1160,7 +1255,8 @@ public: AttributeList *Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent, bool ScopedEnum, + bool &OwnedDecl, bool &IsDependent, + SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType); Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, @@ -1208,7 +1304,7 @@ public: bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); - void ActOnLastBitfield(SourceLocation DeclStart, + void ActOnLastBitfield(SourceLocation DeclStart, SmallVectorImpl<Decl *> &AllIvarDecls); Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, @@ -1245,8 +1341,8 @@ public: /// scope for parsing/looking-up C constructs. /// /// Must be followed by a call to \see ActOnObjCReenterContainerContext - void ActOnObjCTemporaryExitContainerContext(); - void ActOnObjCReenterContainerContext(); + void ActOnObjCTemporaryExitContainerContext(DeclContext *DC); + void ActOnObjCReenterContainerContext(DeclContext *DC); /// ActOnTagDefinitionError - Invoked when there was an unrecoverable /// error parsing the definition of a tag. @@ -1257,6 +1353,9 @@ public: SourceLocation IdLoc, IdentifierInfo *Id, Expr *val); + bool CheckEnumUnderlyingType(TypeSourceInfo *TI); + bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, + QualType EnumUnderlyingTy, const EnumDecl *Prev); Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, @@ -1280,7 +1379,7 @@ public: /// Push the parameters of D, which must be a function, into scope. void ActOnReenterFunctionContext(Scope* S, Decl* D); - void ActOnExitFunctionContext() { PopDeclContext(); } + void ActOnExitFunctionContext(); DeclContext *getFunctionLevelDeclContext(); @@ -1302,6 +1401,14 @@ public: /// Add this decl to the scope shadowed decl chains. void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); + /// \brief Make the given externally-produced declaration visible at the + /// top level scope. + /// + /// \param D The externally-produced declaration to push. + /// + /// \param Name The name of the externally-produced declaration. + void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name); + /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. @@ -1319,14 +1426,17 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); + bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); + void mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation = true); void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); - bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); - bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); - void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old); + bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S); + bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, + Scope *S); + void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); - bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); + bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); // AssignmentAction - This is used by all the assignment diagnostic functions // to represent what is actually causing the operation @@ -1355,7 +1465,7 @@ public: Ovl_NonFunction }; OverloadKind CheckOverload(Scope *S, - FunctionDecl *New, + FunctionDecl *New, const LookupResult &OldDecls, NamedDecl *&OldDecl, bool IsForUsingDecl); @@ -1388,9 +1498,12 @@ public: QualType &ConvertedType); bool IsBlockPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType); - bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType, - const FunctionProtoType *NewType); - + bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType, + unsigned *ArgPos = 0); + void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, + QualType FromType, QualType ToType); + CastKind PrepareCastToObjCObjectPointer(ExprResult &E); bool CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, @@ -1421,7 +1534,8 @@ public: ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, - bool TopLevelOfInitList = false); + bool TopLevelOfInitList = false, + bool AllowExplicit = false); ExprResult PerformObjectArgumentInitialization(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -1430,7 +1544,16 @@ public: ExprResult PerformContextuallyConvertToBool(Expr *From); ExprResult PerformContextuallyConvertToObjCPointer(Expr *From); - ExprResult + /// Contexts in which a converted constant expression is required. + enum CCEKind { + CCEK_CaseValue, ///< Expression in a case label. + CCEK_Enumerator, ///< Enumerator value with fixed underlying type. + CCEK_TemplateArg ///< Value of a non-type template parameter. + }; + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, + llvm::APSInt &Value, CCEKind CCE); + + ExprResult ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, const PartialDiagnostic &NotIntDiag, const PartialDiagnostic &IncompleteDiag, @@ -1438,8 +1561,15 @@ public: const PartialDiagnostic &ExplicitConvNote, const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag); - + const PartialDiagnostic &ConvDiag, + bool AllowScopedEnumerations); + enum ObjCSubscriptKind { + OS_Array, + OS_Dictionary, + OS_Error + }; + ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); + ExprResult PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -1450,21 +1580,18 @@ public: typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet; typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; - void AddOverloadCandidate(NamedDecl *Function, - DeclAccessPair FoundDecl, - Expr **Args, unsigned NumArgs, - OverloadCandidateSet &CandidateSet); - void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false); + bool PartialOverloading = false, + bool AllowExplicit = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions = false); + bool SuppressUserConversions = false, + TemplateArgumentListInfo *ExplicitTemplateArgs = 0); void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, @@ -1475,7 +1602,7 @@ public: DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, @@ -1484,13 +1611,13 @@ public: TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); void AddConversionCandidate(CXXConversionDecl *Conversion, @@ -1507,7 +1634,7 @@ public: DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, - Expr *Object, Expr **Args, unsigned NumArgs, + Expr *Object, llvm::ArrayRef<Expr*> Args, OverloadCandidateSet& CandidateSet); void AddMemberOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, @@ -1524,20 +1651,20 @@ public: Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, - bool Operator, - Expr **Args, unsigned NumArgs, + bool Operator, SourceLocation Loc, + llvm::ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading = false, bool StdNamespaceIsAssociated = false); // Emit as a 'note' the specific overload candidate - void NoteOverloadCandidate(FunctionDecl *Fn); - + void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType()); + // Emit as a series of 'note's all template and non-templates // identified by the expression Expr - void NoteAllOverloadCandidates(Expr* E); - + void NoteAllOverloadCandidates(Expr* E, QualType DestType = QualType()); + // [PossiblyAFunctionType] --> [Return] // NonFunctionType --> NonFunctionType // R (A) --> R(A) @@ -1546,9 +1673,12 @@ public: // R (S::*)(A) --> R (A) QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType); - FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, - bool Complain, - DeclAccessPair &Found); + FunctionDecl * + ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, + QualType TargetType, + bool Complain, + DeclAccessPair &Found, + bool *pHadMultipleCandidates = 0); FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain = false, @@ -1557,9 +1687,9 @@ public: bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool DoFunctionPointerConverion = false, - bool Complain = false, - const SourceRange& OpRangeForComplaining = SourceRange(), - QualType DestTypeForComplaining = QualType(), + bool Complain = false, + const SourceRange& OpRangeForComplaining = SourceRange(), + QualType DestTypeForComplaining = QualType(), unsigned DiagIDForComplaining = 0); @@ -1571,7 +1701,7 @@ public: FunctionDecl *Fn); void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); @@ -1580,7 +1710,8 @@ public: SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, - Expr *ExecConfig); + Expr *ExecConfig, + bool AllowTypoCorrection=true); ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, @@ -1702,8 +1833,21 @@ public: ForRedeclaration }; -private: - bool CppLookupName(LookupResult &R, Scope *S); + /// \brief The possible outcomes of name lookup for a literal operator. + enum LiteralOperatorLookupResult { + /// \brief The lookup resulted in an error. + LOLR_Error, + /// \brief The lookup found a single 'cooked' literal operator, which + /// expects a normal literal to be built and passed to it. + LOLR_Cooked, + /// \brief The lookup found a single 'raw' literal operator, which expects + /// a string literal containing the spelling of the literal token. + LOLR_Raw, + /// \brief The lookup found an overload set of literal operator templates, + /// which expect the characters of the spelling of the literal token to be + /// passed as a non-type template argument pack. + LOLR_Template + }; SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, @@ -1713,6 +1857,9 @@ private: bool ConstThis, bool VolatileThis); +private: + bool CppLookupName(LookupResult &R, Scope *S); + // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls. // // The boolean value will be true to indicate that the namespace was loaded @@ -1722,7 +1869,7 @@ private: /// \brief Whether we have already loaded known namespaces from an extenal /// source. bool LoadedExternalKnownNamespaces; - + public: /// \brief Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. @@ -1741,7 +1888,9 @@ public: bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); - ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc); + ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, + RedeclarationKind Redecl + = NotForRedeclaration); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, @@ -1763,8 +1912,13 @@ public: unsigned ThisQuals); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); + LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, + ArrayRef<QualType> ArgTys, + bool AllowRawAndTemplate); + void ArgumentDependentLookup(DeclarationName Name, bool Operator, - Expr **Args, unsigned NumArgs, + SourceLocation Loc, + llvm::ArrayRef<Expr *> Args, ADLResult &Functions, bool StdNamespaceIsAssociated = false); @@ -1774,43 +1928,16 @@ public: void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope = true); - - /// \brief The context in which typo-correction occurs. - /// - /// The typo-correction context affects which keywords (if any) are - /// considered when trying to correct for typos. - enum CorrectTypoContext { - /// \brief An unknown context, where any keyword might be valid. - CTC_Unknown, - /// \brief A context where no keywords are used (e.g. we expect an actual - /// name). - CTC_NoKeywords, - /// \brief A context where we're correcting a type name. - CTC_Type, - /// \brief An expression context. - CTC_Expression, - /// \brief A type cast, or anything else that can be followed by a '<'. - CTC_CXXCasts, - /// \brief A member lookup context. - CTC_MemberLookup, - /// \brief An Objective-C ivar lookup context (e.g., self->ivar). - CTC_ObjCIvarLookup, - /// \brief An Objective-C property lookup context (e.g., self.prop). - CTC_ObjCPropertyLookup, - /// \brief The receiver of an Objective-C message send within an - /// Objective-C method where 'super' is a valid keyword. - CTC_ObjCMessageReceiver - }; TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - DeclContext *MemberContext = NULL, + CorrectionCandidateCallback &CCC, + DeclContext *MemberContext = 0, bool EnteringContext = false, - CorrectTypoContext CTC = CTC_Unknown, - const ObjCObjectPointerType *OPT = NULL); + const ObjCObjectPointerType *OPT = 0); - void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, + void FindAssociatedClassesAndNamespaces(llvm::ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); @@ -1852,7 +1979,7 @@ public: void WarnConflictingTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl, bool IsProtocolMethodDecl); - + void CheckConflictingOverridingMethod(ObjCMethodDecl *Method, ObjCMethodDecl *Overridden, bool IsProtocolMethodDecl); @@ -1868,7 +1995,7 @@ public: typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet; typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap; - + /// CheckProtocolMethodDefs - This routine checks unimplemented /// methods declared in protocol, and those referenced by it. /// \param IDecl - Used for checking for methods which may have been @@ -1898,18 +2025,18 @@ public: ObjCContainerDecl *CDecl, const SelectorSet &InsMap); - /// DefaultSynthesizeProperties - This routine default synthesizes all + /// DefaultSynthesizeProperties - This routine default synthesizes all /// properties which must be synthesized in class's @implementation. void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl); void DefaultSynthesizeProperties(Scope *S, Decl *D); - + /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. void CollectImmediateProperties(ObjCContainerDecl *CDecl, llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap); - + /// LookupPropertyDecl - Looks up a property in the current class and all /// its protocols. @@ -1920,12 +2047,14 @@ public: //// class extensions. Decl *HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, const bool isAssign, const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, bool *isOverridingProperty, TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind); @@ -1935,12 +2064,14 @@ public: ObjCPropertyDecl *CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, const bool isAssign, const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC = 0); @@ -1976,13 +2107,16 @@ public: ObjCContainerDecl* IDecl, bool &IncompleteImpl, bool ImmediateClass, - bool WarnExactMatch=false); + bool WarnCategoryMethodImpl=false); /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in /// category matches with those implemented in its primary class and - /// warns each time an exact match is found. + /// warns each time an exact match is found. void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); + /// \brief Add the given method to the list of globally-known methods. + void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); + private: /// AddMethodToGlobalPool - Add an instance or factory method to the global /// pool. See descriptoin of AddInstanceMethodToGlobalPool. @@ -2017,7 +2151,7 @@ public: ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, bool receiverIdOrClass=false, bool warn=true) { - return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, warn, /*instance*/true); } @@ -2045,7 +2179,7 @@ public: class FullExprArg { public: FullExprArg(Sema &actions) : E(0) { } - + // FIXME: The const_cast here is ugly. RValue references would make this // much nicer (or we could duplicate a bunch of the move semantics // emulation code from Ownership.h). @@ -2079,9 +2213,28 @@ public: StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro = false); + + void ActOnStartOfCompoundStmt(); + void ActOnFinishOfCompoundStmt(); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg Elts, bool isStmtExpr); + + /// \brief A RAII object to enter scope of a compound statement. + class CompoundScopeRAII { + public: + CompoundScopeRAII(Sema &S): S(S) { + S.ActOnStartOfCompoundStmt(); + } + + ~CompoundScopeRAII() { + S.ActOnFinishOfCompoundStmt(); + } + + private: + Sema &S; + }; + StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc); @@ -2097,7 +2250,7 @@ public: Stmt *SubStmt, Scope *CurScope); StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, SourceLocation ColonLoc, Stmt *SubStmt); - + StmtResult ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *ThenVal, @@ -2151,9 +2304,9 @@ public: const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, bool AllowFunctionParameters); - + StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); - StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); + StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); StmtResult ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, @@ -2220,7 +2373,7 @@ public: void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; - + /// \brief If it's a file scoped decl that must warn if not used, keep track /// of it. void MarkUnusedFileScopedDecl(const DeclaratorDecl *D); @@ -2229,7 +2382,22 @@ public: /// whose result is unused, warn. void DiagnoseUnusedExprResult(const Stmt *S); void DiagnoseUnusedDecl(const NamedDecl *ND); - + + /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null + /// statement as a \p Body, and it is located on the same line. + /// + /// This helps prevent bugs due to typos, such as: + /// if (condition); + /// do_stuff(); + void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, + const Stmt *Body, + unsigned DiagID); + + /// Warn if a for/while loop statement \p S, which is followed by + /// \p PossibleBody, has a suspicious null statement as a body. + void DiagnoseEmptyLoopBody(const Stmt *S, + const Stmt *PossibleBody); + ParsingDeclState PushParsingDeclaration() { return DelayedDiagnostics.pushParsingDecl(); } @@ -2246,7 +2414,7 @@ public: } void EmitDeprecationWarning(NamedDecl *D, StringRef Message, - SourceLocation Loc, + SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass=0); void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -2260,6 +2428,7 @@ public: bool CanUseDecl(NamedDecl *D); bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass=0); + void NoteDeletedFunction(FunctionDecl *FD); std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, @@ -2267,15 +2436,82 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs); - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); + void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = 0, + bool IsDecltype = false); void PopExpressionEvaluationContext(); void DiscardCleanupsInEvaluationContext(); - void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); + ExprResult TranformToPotentiallyEvaluated(Expr *E); + ExprResult HandleExprEvaluationContextForTypeof(Expr *E); + + ExprResult ActOnConstantExpression(ExprResult Res); + + // Functions for marking a declaration referenced. These functions also + // contain the relevant logic for marking if a reference to a function or + // variable is an odr-use (in the C++11 sense). There are separate variants + // for expressions referring to a decl; these exist because odr-use marking + // needs to be delayed for some constant variables when we build one of the + // named expressions. + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D); + void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func); + void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); + void MarkDeclRefReferenced(DeclRefExpr *E); + void MarkMemberReferenced(MemberExpr *E); + + void UpdateMarkingForLValueToRValue(Expr *E); + void CleanupVarDeclMarking(); + + enum TryCaptureKind { + TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef + }; + + /// \brief Try to capture the given variable. + /// + /// \param Var The variable to capture. + /// + /// \param Loc The location at which the capture occurs. + /// + /// \param Kind The kind of capture, which may be implicit (for either a + /// block or a lambda), or explicit by-value or by-reference (for a lambda). + /// + /// \param EllipsisLoc The location of the ellipsis, if one is provided in + /// an explicit lambda capture. + /// + /// \param BuildAndDiagnose Whether we are actually supposed to add the + /// captures or diagnose errors. If false, this routine merely check whether + /// the capture can occur without performing the capture itself or complaining + /// if the variable cannot be captured. + /// + /// \param CaptureType Will be set to the type of the field used to capture + /// this variable in the innermost block or lambda. Only valid when the + /// variable can be captured. + /// + /// \param DeclRefType Will be set to the type of a refernce to the capture + /// from within the current scope. Only valid when the variable can be + /// captured. + /// + /// \returns true if an error occurred (i.e., the variable cannot be + /// captured) and false if the capture succeeded. + bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind, + SourceLocation EllipsisLoc, bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType); + + /// \brief Try to capture the given variable. + bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + TryCaptureKind Kind = TryCapture_Implicit, + SourceLocation EllipsisLoc = SourceLocation()); + + /// \brief Given a variable, determine the type that a reference to that + /// variable will have in the given scope. + QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); + void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); - void MarkDeclarationsReferencedInExpr(Expr *E); + void MarkDeclarationsReferencedInExpr(Expr *E, + bool SkipLocalVariables = false); /// \brief Try to recover by turning the given expression into a /// call. Returns true if recovery was attempted or an error was @@ -2300,9 +2536,12 @@ public: // Primary Expressions. SourceRange getExprRange(Expr *E) const; - - ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Id, - bool HasTrailingLParen, bool IsAddressOfOperand); + + ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Id, + bool HasTrailingLParen, bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = 0); void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, @@ -2310,15 +2549,16 @@ public: const TemplateArgumentListInfo *&TemplateArgs); bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectTypoContext CTC = CTC_Unknown, + CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = 0, - Expr **Args = 0, unsigned NumArgs = 0); + llvm::ArrayRef<Expr *> Args = llvm::ArrayRef<Expr *>()); ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, bool AllowBuiltinCreation=false); ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs); @@ -2338,9 +2578,11 @@ public: Expr *baseObjectExpr = 0, SourceLocation opLoc = SourceLocation()); ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs); ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, bool IsDefiniteInstance); @@ -2351,6 +2593,7 @@ public: ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo); ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2361,18 +2604,25 @@ public: const DeclarationNameInfo &NameInfo, NamedDecl *D); + ExprResult BuildLiteralOperatorCall(LookupResult &R, + DeclarationNameInfo &SuffixInfo, + ArrayRef<Expr*> Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *ExplicitTemplateArgs = 0); + ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); - ExprResult ActOnNumericConstant(const Token &Tok); - ExprResult ActOnCharacterConstant(const Token &Tok); + ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); + ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0); + ExprResult ActOnCharacterConstant(const Token &Tok, Scope *UDLScope = 0); ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E); - ExprResult ActOnParenOrParenListExpr(SourceLocation L, - SourceLocation R, - MultiExprArg Val); + ExprResult ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val); /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). - ExprResult ActOnStringLiteral(const Token *StringToks, - unsigned NumStringToks); + ExprResult ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, + Scope *UDLScope = 0); ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, @@ -2431,6 +2681,7 @@ public: ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2438,11 +2689,13 @@ public: ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, bool SuppressQualifierCheck = false); + ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, @@ -2456,6 +2709,7 @@ public: ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2464,6 +2718,7 @@ public: SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Member, Decl *ObjCImpDecl, bool HasTrailingLParen); @@ -2475,6 +2730,9 @@ public: Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, bool ExecConfig = false); + void CheckStaticArrayArgument(SourceLocation CallLoc, + ParmVarDecl *Param, + const Expr *ArgExpr); /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma @@ -2544,9 +2802,11 @@ public: /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl); - + + void ActOnStartStmtExpr(); ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, SourceLocation RPLoc); // "({..})" + void ActOnStmtExprError(); // __builtin_offsetof(type, identifier(.identifier|[expr])*) struct OffsetOfComponent { @@ -2588,7 +2848,40 @@ public: bool CheckCaseExpression(Expr *E); - bool CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, UnqualifiedId &Name); + /// \brief Describes the result of an "if-exists" condition check. + enum IfExistsResult { + /// \brief The symbol exists. + IER_Exists, + + /// \brief The symbol does not exist. + IER_DoesNotExist, + + /// \brief The name is a dependent name, so the results will differ + /// from one instantiation to the next. + IER_Dependent, + + /// \brief An error occurred. + IER_Error + }; + + IfExistsResult + CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS, + const DeclarationNameInfo &TargetNameInfo); + + IfExistsResult + CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, + bool IsIfExists, CXXScopeSpec &SS, + UnqualifiedId &Name); + + StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + Stmt *Nested); + StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + CXXScopeSpec &SS, UnqualifiedId &Name, + Stmt *Nested); //===------------------------- "Block" Extension ------------------------===// @@ -2610,12 +2903,12 @@ public: Scope *CurScope); //===---------------------------- OpenCL Features -----------------------===// - + /// __builtin_astype(...) ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, - SourceLocation BuiltinLoc, + SourceLocation BuiltinLoc, SourceLocation RParenLoc); - + //===---------------------------- C++ Features --------------------------===// // Act on C++ namespaces @@ -2632,6 +2925,20 @@ public: CXXRecordDecl *getStdBadAlloc() const; + /// \brief Tests whether Ty is an instance of std::initializer_list and, if + /// it is and Element is not NULL, assigns the element type to Element. + bool isStdInitializerList(QualType Ty, QualType *Element); + + /// \brief Looks for the std::initializer_list template and instantiates it + /// with Element, or emits an error if it's not found. + /// + /// \returns The instantiated template, or null on error. + QualType BuildStdInitializerList(QualType Element, SourceLocation Loc); + + /// \brief Determine whether Ctor is an initializer-list constructor, as + /// defined in [dcl.init.list]p2. + bool isInitListConstructor(const CXXConstructorDecl *Ctor); + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -2674,7 +2981,7 @@ public: bool IsTypeName, SourceLocation TypenameLoc); - bool CheckInheritedConstructorUsingDecl(UsingDecl *UD); + bool CheckInheritingConstructorUsingDecl(UsingDecl *UD); Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, @@ -2692,15 +2999,6 @@ public: UnqualifiedId &Name, TypeResult Type); - /// AddCXXDirectInitializerToDecl - This action is called immediately after - /// ActOnDeclarator, when a C++ direct initializer is present. - /// e.g: "int x(1);" - void AddCXXDirectInitializerToDecl(Decl *Dcl, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation RParenLoc, - bool TypeMayContainAuto); - /// InitializeVarWithConstructor - Creates an CXXConstructExpr /// and sets it as the initializer for the the passed in VarDecl. bool InitializeVarWithConstructor(VarDecl *VD, @@ -2737,7 +3035,7 @@ public: /// constructed variable. void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); - /// \brief Helper class that collects exception specifications for + /// \brief Helper class that collects exception specifications for /// implicitly-declared special member functions. class ImplicitExceptionSpecification { // Pointer to allow copying @@ -2765,9 +3063,9 @@ public: } public: - explicit ImplicitExceptionSpecification(ASTContext &Context) + explicit ImplicitExceptionSpecification(ASTContext &Context) : Context(&Context), ComputedEST(EST_BasicNoexcept) { - if (!Context.getLangOptions().CPlusPlus0x) + if (!Context.getLangOpts().CPlusPlus0x) ComputedEST = EST_DynamicNone; } @@ -2839,28 +3137,18 @@ public: /// \brief Determine if a special member function should have a deleted /// definition when it is defaulted. - bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM); - - /// \brief Determine if a defaulted copy assignment operator ought to be - /// deleted. - bool ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD); - - /// \brief Determine if a defaulted move assignment operator ought to be - /// deleted. - bool ShouldDeleteMoveAssignmentOperator(CXXMethodDecl *MD); - - /// \brief Determine if a defaulted destructor ought to be deleted. - bool ShouldDeleteDestructor(CXXDestructorDecl *DD); + bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose = false); /// \brief Declare the implicit default constructor for the given class. /// - /// \param ClassDecl The class declaration into which the implicit + /// \param ClassDecl The class declaration into which the implicit /// default constructor will be added. /// /// \returns The implicitly-declared default constructor. CXXConstructorDecl *DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl); - + /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, @@ -2868,12 +3156,12 @@ public: /// \brief Declare the implicit destructor for the given class. /// - /// \param ClassDecl The class declaration into which the implicit + /// \param ClassDecl The class declaration into which the implicit /// destructor will be added. /// /// \returns The implicitly-declared destructor. CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); - + /// DefineImplicitDestructor - Checks for feasibility of /// defining this destructor as the default destructor. void DefineImplicitDestructor(SourceLocation CurrentLocation, @@ -2894,12 +3182,12 @@ public: /// \brief Declare the implicit copy constructor for the given class. /// - /// \param ClassDecl The class declaration into which the implicit + /// \param ClassDecl The class declaration into which the implicit /// copy constructor will be added. /// /// \returns The implicitly-declared copy constructor. CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); - + /// DefineImplicitCopyConstructor - Checks for feasibility of /// defining this constructor as the copy constructor. void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, @@ -2913,7 +3201,7 @@ public: /// \returns The implicitly-declared move constructor, or NULL if it wasn't /// declared. CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl); - + /// DefineImplicitMoveConstructor - Checks for feasibility of /// defining this constructor as the move constructor. void DefineImplicitMoveConstructor(SourceLocation CurrentLocation, @@ -2921,12 +3209,12 @@ public: /// \brief Declare the implicit copy assignment operator for the given class. /// - /// \param ClassDecl The class declaration into which the implicit + /// \param ClassDecl The class declaration into which the implicit /// copy assignment operator will be added. /// /// \returns The implicitly-declared copy assignment operator. CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); - + /// \brief Defines an implicitly-declared copy assignment operator. void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MethodDecl); @@ -2939,7 +3227,7 @@ public: /// \returns The implicitly-declared move assignment operator, or NULL if it /// wasn't declared. CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl); - + /// \brief Defines an implicitly-declared move assignment operator. void DefineImplicitMoveAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MethodDecl); @@ -2947,6 +3235,10 @@ public: /// \brief Force the declaration of any implicitly-declared members of this /// class. void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); + + /// \brief Determine whether the given function is an implicitly-deleted + /// special member function. + bool isImplicitlyDeleted(FunctionDecl *FD); /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise @@ -2956,7 +3248,8 @@ public: bool CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<Expr*> &ConvertedArgs); + ASTOwningVector<Expr*> &ConvertedArgs, + bool AllowExplicit = false); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, @@ -2964,6 +3257,8 @@ public: ParsedType ObjectType, bool EnteringContext); + ParsedType getDestructorType(const DeclSpec& DS, ParsedType ObjectType); + // Checks that reinterpret casts don't have undefined behavior. void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, bool IsDereference, SourceRange Range); @@ -3019,21 +3314,37 @@ public: //// ActOnCXXThis - Parse 'this' pointer. ExprResult ActOnCXXThis(SourceLocation loc); - /// getAndCaptureCurrentThisType - Try to capture a 'this' pointer. Returns - /// the type of the 'this' pointer, or a null type if this is not possible. - QualType getAndCaptureCurrentThisType(); + /// \brief Try to retrieve the type of the 'this' pointer. + /// + /// \param Capture If true, capture 'this' in this context. + /// + /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. + QualType getCurrentThisType(); + + /// \brief Make sure the value of 'this' is actually available in the current + /// context, if it is a potentially evaluated context. + /// + /// \param Loc The location at which the capture of 'this' occurs. + /// + /// \param Explicit Whether 'this' is explicitly captured in a lambda + /// capture list. + void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false); /// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); + + + /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. + ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); //// ActOnCXXThrow - Parse throw expressions. ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr); - ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, + ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, bool IsThrownVarInScope); - ExprResult CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, + ExprResult CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, bool IsThrownVarInScope); /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. @@ -3056,9 +3367,7 @@ public: MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen); + Expr *Initializer); ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -3067,9 +3376,8 @@ public: QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen, + SourceRange DirectInitRange, + Expr *Initializer, bool TypeMayContainAuto = true); bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, @@ -3134,6 +3442,14 @@ public: TypeSourceInfo *RhsT, SourceLocation RParen); + /// \brief Parsed one of the type trait support pseudo-functions. + ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef<ParsedType> Args, + SourceLocation RParenLoc); + ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc); + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support /// pseudo-functions. ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, @@ -3189,6 +3505,13 @@ public: UnqualifiedId &SecondTypeName, bool HasTrailingLParen); + ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation TildeLoc, + const DeclSpec& DS, + bool HasTrailingLParen); + /// MaybeCreateExprWithCleanups - If the current full-expression /// requires any cleanups, surround it with a ExprWithCleanups node. /// Otherwise, just returns the passed-in expression. @@ -3221,7 +3544,7 @@ public: /// \returns true if an error occurred, false otherwise. bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, CXXScopeSpec &SS); - + bool isAcceptableNestedNameSpecifier(NamedDecl *SD); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); @@ -3250,7 +3573,7 @@ public: /// /// \param CCLoc The location of the '::'. /// - /// \param ObjectType The type of the object, if we're parsing + /// \param ObjectType The type of the object, if we're parsing /// nested-name-specifier in a member access expression. /// /// \param EnteringContext Whether we're entering the context nominated by @@ -3270,6 +3593,12 @@ public: bool EnteringContext, CXXScopeSpec &SS); + ExprResult ActOnDecltypeExpression(Expr *E); + + bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, + const DeclSpec &DS, + SourceLocation ColonColonLoc); + bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, IdentifierInfo &Identifier, SourceLocation IdentifierLoc, @@ -3277,34 +3606,32 @@ public: ParsedType ObjectType, bool EnteringContext); - /// \brief The parser has parsed a nested-name-specifier + /// \brief The parser has parsed a nested-name-specifier /// 'template[opt] template-name < template-args >::'. /// /// \param S The scope in which this nested-name-specifier occurs. /// - /// \param TemplateLoc The location of the 'template' keyword, if any. - /// /// \param SS The nested-name-specifier, which is both an input /// parameter (the nested-name-specifier before this type) and an /// output parameter (containing the full nested-name-specifier, /// including this new type). - /// - /// \param TemplateLoc the location of the 'template' keyword, if any. + /// + /// \param TemplateKWLoc the location of the 'template' keyword, if any. /// \param TemplateName The template name. /// \param TemplateNameLoc The location of the template name. /// \param LAngleLoc The location of the opening angle bracket ('<'). /// \param TemplateArgs The template arguments. /// \param RAngleLoc The location of the closing angle bracket ('>'). /// \param CCLoc The location of the '::'. - - /// \param EnteringContext Whether we're entering the context of the + /// + /// \param EnteringContext Whether we're entering the context of the /// nested-name-specifier. /// /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, - SourceLocation TemplateLoc, - CXXScopeSpec &SS, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, @@ -3314,29 +3641,29 @@ public: bool EnteringContext); /// \brief Given a C++ nested-name-specifier, produce an annotation value - /// that the parser can use later to reconstruct the given + /// that the parser can use later to reconstruct the given /// nested-name-specifier. /// /// \param SS A nested-name-specifier. /// - /// \returns A pointer containing all of the information in the + /// \returns A pointer containing all of the information in the /// nested-name-specifier \p SS. void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); - - /// \brief Given an annotation pointer for a nested-name-specifier, restore + + /// \brief Given an annotation pointer for a nested-name-specifier, restore /// the nested-name-specifier structure. /// - /// \param Annotation The annotation pointer, produced by + /// \param Annotation The annotation pointer, produced by /// \c SaveNestedNameSpecifierAnnotation(). /// /// \param AnnotationRange The source range corresponding to the annotation. /// /// \param SS The nested-name-specifier that will be updated with the contents /// of the annotation pointer. - void RestoreNestedNameSpecifierAnnotation(void *Annotation, + void RestoreNestedNameSpecifierAnnotation(void *Annotation, SourceRange AnnotationRange, CXXScopeSpec &SS); - + bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global @@ -3365,16 +3692,107 @@ public: /// initializer for the declaration 'Dcl'. void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); + /// \brief Create a new lambda closure type. + CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, + bool KnownDependent = false); + + /// \brief Start the definition of a lambda expression. + CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodType, + SourceLocation EndLoc, + llvm::ArrayRef<ParmVarDecl *> Params, + llvm::Optional<unsigned> ManglingNumber + = llvm::Optional<unsigned>(), + Decl *ContextDecl = 0); + + /// \brief Introduce the scope for a lambda expression. + sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + bool ExplicitParams, + bool ExplicitResultType, + bool Mutable); + + /// \brief Note that we have finished the explicit captures for the + /// given lambda. + void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); + + /// \brief Introduce the lambda parameters into scope. + void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope); + + /// ActOnStartOfLambdaDefinition - This is called just before we start + /// parsing the body of a lambda; it analyzes the explicit captures and + /// arguments, and sets up various data-structures for the body of the + /// lambda. + void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, Scope *CurScope); + + /// ActOnLambdaError - If there is an error parsing a lambda, this callback + /// is invoked to pop the information about the lambda. + void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, + bool IsInstantiation = false); + + /// ActOnLambdaExpr - This is called when the body of a lambda expression + /// was successfully completed. + ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, + Scope *CurScope, + bool IsInstantiation = false); + + /// \brief Define the "body" of the conversion from a lambda object to a + /// function pointer. + /// + /// This routine doesn't actually define a sensible body; rather, it fills + /// in the initialization expression needed to copy the lambda object into + /// the block, and IR generation actually generates the real body of the + /// block pointer conversion. + void DefineImplicitLambdaToFunctionPointerConversion( + SourceLocation CurrentLoc, CXXConversionDecl *Conv); + + /// \brief Define the "body" of the conversion from a lambda object to a + /// block pointer. + /// + /// This routine doesn't actually define a sensible body; rather, it fills + /// in the initialization expression needed to copy the lambda object into + /// the block, and IR generation actually generates the real body of the + /// block pointer conversion. + void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc, + CXXConversionDecl *Conv); + + ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation, + SourceLocation ConvLocation, + CXXConversionDecl *Conv, + Expr *Src); + // ParseObjCStringLiteral - Parse Objective-C string literals. ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, Expr **Strings, unsigned NumStrings); - + + ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); + + /// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the + /// numeric literal expression. Type of the expression will be "NSNumber *" + /// or "id" if NSNumber is unavailable. + ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); + ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, + bool Value); + ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); + + ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, + Expr *IndexExpr, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod); + + ExprResult BuildObjCDictionaryLiteral(SourceRange SR, + ObjCDictionaryElement *Elements, + unsigned NumElements); + ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, TypeSourceInfo *EncodedTypeInfo, SourceLocation RParenLoc); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, - CXXMethodDecl *Method, + CXXConversionDecl *Method, bool HadMultipleCandidates); ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, @@ -3434,6 +3852,7 @@ public: CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -3445,6 +3864,7 @@ public: CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, Expr *InitList, SourceLocation EllipsisLoc); @@ -3454,23 +3874,23 @@ public: CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, - const MultiInitializer &Init, + Expr *Init, SourceLocation EllipsisLoc); MemInitResult BuildMemberInitializer(ValueDecl *Member, - const MultiInitializer &Args, + Expr *Init, SourceLocation IdLoc); MemInitResult BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, - const MultiInitializer &Args, + Expr *Init, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc); MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, - const MultiInitializer &Args, - SourceLocation BaseLoc, + Expr *Init, CXXRecordDecl *ClassDecl); bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, @@ -3479,9 +3899,9 @@ public: bool SetCtorInitializers(CXXConstructorDecl *Constructor, CXXCtorInitializer **Initializers, unsigned NumInitializers, bool AnyErrors); - + void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); - + /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, /// mark all the non-trivial destructors of its members and bases as @@ -3506,8 +3926,8 @@ public: /// \brief Load any externally-stored vtable uses. void LoadExternalVTableUses(); - - typedef LazyVector<CXXRecordDecl *, ExternalSemaSource, + + typedef LazyVector<CXXRecordDecl *, ExternalSemaSource, &ExternalSemaSource::ReadDynamicClasses, 2, 2> DynamicClassesType; @@ -3563,7 +3983,8 @@ public: Expr *AssertMessageExpr, SourceLocation RParenLoc); - FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, + FriendDecl *CheckFriendTypeDecl(SourceLocation Loc, + SourceLocation FriendLoc, TypeSourceInfo *TSInfo); Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TemplateParams); @@ -3602,7 +4023,7 @@ public: BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, - ParsedType basetype, + ParsedType basetype, SourceLocation BaseLoc, SourceLocation EllipsisLoc); @@ -3652,7 +4073,7 @@ public: /// C++0x [class.virtual]p3. bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old); - + //===--------------------------------------------------------------------===// // C++ Access Control @@ -3685,11 +4106,13 @@ public: bool IsCopyBindingRefToTemp = false); AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, + const InitializedEntity &Entity, AccessSpecifier Access, - PartialDiagnostic PD); + const PartialDiagnostic &PDiag); AccessResult CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, - const PartialDiagnostic &PDiag); + const PartialDiagnostic &PDiag, + QualType objectType = QualType()); AccessResult CheckDirectMemberAccess(SourceLocation Loc, NamedDecl *D, const PartialDiagnostic &PDiag); @@ -3706,7 +4129,10 @@ public: bool ForceCheck = false, bool ForceUnprivileged = false); void CheckLookupAccess(const LookupResult &R); - bool IsSimplyAccessible(NamedDecl *decl, CXXRecordDecl *Class); + bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx); + bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, + AccessSpecifier access, + QualType objectType); void HandleDependentAccessCheck(const DependentDiagnostic &DD, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -3721,7 +4147,27 @@ public: /// \brief When true, access checking violations are treated as SFINAE /// failures rather than hard errors. bool AccessCheckingSFINAE; - + + /// \brief RAII object used to temporarily suppress access checking. + class SuppressAccessChecksRAII { + Sema &S; + bool SuppressingAccess; + + public: + SuppressAccessChecksRAII(Sema &S, bool Suppress) + : S(S), SuppressingAccess(Suppress) { + if (Suppress) S.ActOnStartSuppressingAccessChecks(); + } + ~SuppressAccessChecksRAII() { + done(); + } + void done() { + if (!SuppressingAccess) return; + S.ActOnStopSuppressingAccessChecks(); + SuppressingAccess = false; + } + }; + void ActOnStartSuppressingAccessChecks(); void ActOnStopSuppressingAccessChecks(); @@ -3752,9 +4198,11 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // - void FilterAcceptableTemplateNames(LookupResult &R); - bool hasAnyAcceptableTemplateNames(LookupResult &R); - + void FilterAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates = true); + bool hasAnyAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates = true); + void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization); @@ -3775,7 +4223,7 @@ public: TemplateTy &SuggestedTemplate, TemplateNameKind &SuggestedKind); - bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); + void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, @@ -3841,7 +4289,7 @@ public: IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, unsigned NumOuterTemplateParamLists, TemplateParameterList **OuterTemplateParamLists); @@ -3850,44 +4298,49 @@ public: TemplateArgumentListInfo &Out); void NoteAllFoundTemplates(TemplateName Name); - + QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs); TypeResult - ActOnTemplateIdType(CXXScopeSpec &SS, + ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, TemplateTy Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); + SourceLocation RAngleLoc, + bool IsCtorOrDtorName = false); /// \brief Parsed an elaborated-type-specifier that refers to a template-id, /// such as \c class T::template apply<U>. /// - /// \param TUK + /// \param TUK TypeResult ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, - TemplateTy TemplateD, + SourceLocation TemplateKWLoc, + TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc); - + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, bool RequiresADL, - const TemplateArgumentListInfo &TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs); + ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo &TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs); TemplateNameKind ActOnDependentTemplateName(Scope *S, - SourceLocation TemplateKWLoc, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, @@ -4013,12 +4466,18 @@ public: /// \param Converted Will receive the converted, canonicalized template /// arguments. /// + /// + /// \param ExpansionIntoFixedList If non-NULL, will be set true to indicate + /// when the template arguments contain a pack expansion that is being + /// expanded into a fixed parameter list. + /// /// \returns True if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted); + SmallVectorImpl<TemplateArgument> &Converted, + bool *ExpansionIntoFixedList = 0); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, const TemplateArgumentLoc &Arg, @@ -4026,12 +4485,10 @@ public: bool CheckTemplateArgument(TemplateTypeParmDecl *Param, TypeSourceInfo *Arg); - bool CheckTemplateArgumentPointerToMember(Expr *Arg, - TemplateArgument &Converted); ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *Arg, TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK = CTAK_Specified); + CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, const TemplateArgumentLoc &Arg); @@ -4095,8 +4552,8 @@ public: /// \param II the identifier we're retrieving (e.g., 'type' in the example). /// \param IdLoc the location of the identifier. TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, const IdentifierInfo &II, + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc); /// \brief Called when the parser has parsed a C++ typename @@ -4113,9 +4570,9 @@ public: /// \param TemplateArgs The template arguments. /// \param RAngleLoc The location of the closing angle bracket ('>'). TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, - SourceLocation TemplateLoc, + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, @@ -4136,7 +4593,7 @@ public: ExprResult RebuildExprInCurrentInstantiation(Expr *E); bool RebuildTemplateParamsInCurrentInstantiation( TemplateParameterList *Params); - + std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args); @@ -4191,19 +4648,37 @@ public: /// \brief An initializer. UPPC_Initializer, - + /// \brief A default argument. UPPC_DefaultArgument, - + /// \brief The type of a non-type template parameter. UPPC_NonTypeTemplateParameterType, /// \brief The type of an exception. UPPC_ExceptionType, - + /// \brief Partial specialization. - UPPC_PartialSpecialization - }; + UPPC_PartialSpecialization, + + /// \brief Microsoft __if_exists. + UPPC_IfExists, + + /// \brief Microsoft __if_not_exists. + UPPC_IfNotExists +}; + + /// \brief Diagnose unexpanded parameter packs. + /// + /// \param Loc The location at which we should emit the diagnostic. + /// + /// \param UPPC The context in which we are diagnosing unexpanded + /// parameter packs. + /// + /// \param Unexpanded the set of unexpanded parameter packs. + void DiagnoseUnexpandedParameterPacks(SourceLocation Loc, + UnexpandedParameterPackContext UPPC, + ArrayRef<UnexpandedParameterPack> Unexpanded); /// \brief If the given type contains an unexpanded parameter pack, /// diagnose the error. @@ -4252,7 +4727,7 @@ public: /// /// \param Loc The location of the template name. /// - /// \param Template The template name that is being checked for unexpanded + /// \param Template The template name that is being checked for unexpanded /// parameter packs. /// /// \returns true if an error occurred, false otherwise. @@ -4260,18 +4735,18 @@ public: TemplateName Template, UnexpandedParameterPackContext UPPC); - /// \brief If the given template argument contains an unexpanded parameter + /// \brief If the given template argument contains an unexpanded parameter /// pack, diagnose the error. /// - /// \param Arg The template argument that is being checked for unexpanded + /// \param Arg The template argument that is being checked for unexpanded /// parameter packs. /// /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, UnexpandedParameterPackContext UPPC); - + /// \brief Collect the set of unexpanded parameter packs within the given - /// template argument. + /// template argument. /// /// \param Arg The template argument that will be traversed to find /// unexpanded parameter packs. @@ -4279,7 +4754,7 @@ public: SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); /// \brief Collect the set of unexpanded parameter packs within the given - /// template argument. + /// template argument. /// /// \param Arg The template argument that will be traversed to find /// unexpanded parameter packs. @@ -4287,7 +4762,7 @@ public: SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); /// \brief Collect the set of unexpanded parameter packs within the given - /// type. + /// type. /// /// \param T The type that will be traversed to find /// unexpanded parameter packs. @@ -4295,13 +4770,29 @@ public: SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); /// \brief Collect the set of unexpanded parameter packs within the given - /// type. + /// type. /// /// \param TL The type that will be traversed to find /// unexpanded parameter packs. void collectUnexpandedParameterPacks(TypeLoc TL, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); + /// \brief Collect the set of unexpanded parameter packs within the given + /// nested-name-specifier. + /// + /// \param SS The nested-name-specifier that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks(CXXScopeSpec &SS, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); + + /// \brief Collect the set of unexpanded parameter packs within the given + /// name. + /// + /// \param NameInfo The name that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); + /// \brief Invoked when parsing a template argument followed by an /// ellipsis, which creates a pack expansion. /// @@ -4363,7 +4854,7 @@ public: /// \param PatternRange The source range that covers the entire pattern of /// the pack expansion. /// - /// \param Unexpanded The set of unexpanded parameter packs within the + /// \param Unexpanded The set of unexpanded parameter packs within the /// pattern. /// /// \param NumUnexpanded The number of unexpanded parameter packs in @@ -4386,9 +4877,9 @@ public: /// The callee must set this value when \c ShouldExpand is \c true; it may /// set this value in other cases. /// - /// \returns true if an error occurred (e.g., because the parameter packs - /// are to be instantiated with arguments of different lengths), false - /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) + /// \returns true if an error occurred (e.g., because the parameter packs + /// are to be instantiated with arguments of different lengths), false + /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) /// must be set. bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, @@ -4404,9 +4895,9 @@ public: /// This routine already assumes that the pack expansion type can be /// expanded and that the number of arguments in the expansion is /// consistent across all of the unexpanded parameter packs in its pattern. - unsigned getNumArgumentsInExpansion(QualType T, + unsigned getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); - + /// \brief Determine whether the given declarator contains any unexpanded /// parameter packs. /// @@ -4423,11 +4914,11 @@ public: /// \returns true if the declarator contains any unexpanded parameter packs, /// false otherwise. bool containsUnexpandedParameterPacks(Declarator &D); - + //===--------------------------------------------------------------------===// // C++ Template Argument Deduction (C++ [temp.deduct]) //===--------------------------------------------------------------------===// - + /// \brief Describes the result of template argument deduction. /// /// The TemplateDeductionResult enumeration describes the result of @@ -4489,20 +4980,20 @@ public: QualType *FunctionType, sema::TemplateDeductionInfo &Info); - /// brief A function argument from which we performed template argument + /// brief A function argument from which we performed template argument // deduction for a call. struct OriginalCallArg { OriginalCallArg(QualType OriginalParamType, unsigned ArgIdx, QualType OriginalArgType) - : OriginalParamType(OriginalParamType), ArgIdx(ArgIdx), + : OriginalParamType(OriginalParamType), ArgIdx(ArgIdx), OriginalArgType(OriginalArgType) { } - + QualType OriginalParamType; unsigned ArgIdx; QualType OriginalArgType; }; - + TemplateDeductionResult FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, SmallVectorImpl<DeducedTemplateArgument> &Deduced, @@ -4514,7 +5005,7 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, + llvm::ArrayRef<Expr *> Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); @@ -4537,8 +5028,16 @@ public: FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); - bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer, - TypeSourceInfo *&Result); + /// \brief Result type of DeduceAutoType. + enum DeduceAutoResult { + DAR_Succeeded, + DAR_Failed, + DAR_FailedAlreadyDiagnosed + }; + + DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, + TypeSourceInfo *&Result); + void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, @@ -4553,7 +5052,8 @@ public: const PartialDiagnostic &NoneDiag, const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag, - bool Complain = true); + bool Complain = true, + QualType TargetType = QualType()); ClassTemplatePartialSpecializationDecl * getMoreSpecializedPartialSpecialization( @@ -4564,9 +5064,14 @@ public: void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, unsigned Depth, - SmallVectorImpl<bool> &Used); + llvm::SmallBitVector &Used); void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl<bool> &Deduced); + llvm::SmallBitVector &Deduced) { + return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced); + } + static void MarkDeducedTemplateParameters(ASTContext &Ctx, + FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced); //===--------------------------------------------------------------------===// // C++ Template Instantiation @@ -4621,8 +5126,8 @@ public: /// \brief The point of instantiation within the source code. SourceLocation PointOfInstantiation; - /// \brief The template (or partial specialization) in which we are - /// performing the instantiation, for substitutions of prior template + /// \brief The template (or partial specialization) in which we are + /// performing the instantiation, for substitutions of prior template /// arguments. NamedDecl *Template; @@ -4636,7 +5141,7 @@ public: /// \brief The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; - /// \brief The template deduction info object associated with the + /// \brief The template deduction info object associated with the /// substitution or checking of explicit or deduced template arguments. sema::TemplateDeductionInfo *DeductionInfo; @@ -4680,7 +5185,7 @@ public: } - return true; + llvm_unreachable("Invalid InstantiationKind!"); } friend bool operator!=(const ActiveTemplateInstantiation &X, @@ -4704,7 +5209,7 @@ public: /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside /// of a template instantiation or template argument deduction. bool InNonInstantiationSFINAEContext; - + /// \brief The number of ActiveTemplateInstantiation entries in /// \c ActiveTemplateInstantiations that are not actual instantiations and, /// therefore, should not be counted as part of the instantiation depth. @@ -4722,7 +5227,7 @@ public: /// \brief The current index into pack expansion arguments that will be /// used for substitution of parameter packs. /// - /// The pack expansion index will be -1 to indicate that parameter packs + /// The pack expansion index will be -1 to indicate that parameter packs /// should be instantiated as themselves. Otherwise, the index specifies /// which argument within the parameter pack will be used for substitution. int ArgumentPackSubstitutionIndex; @@ -4734,26 +5239,26 @@ public: class ArgumentPackSubstitutionIndexRAII { Sema &Self; int OldSubstitutionIndex; - + public: ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex) : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) { Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex; } - + ~ArgumentPackSubstitutionIndexRAII() { Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex; } }; - + friend class ArgumentPackSubstitutionRAII; - + /// \brief The stack of calls expression undergoing template instantiation. /// /// The top of this stack is used by a fixit instantiating unresolved /// function calls to fix the AST to match the textual change it prints. SmallVector<CallExpr *, 8> CallsUndergoingInstantiation; - + /// \brief For each declaration that involved template argument deduction, the /// set of diagnostics that were suppressed during that template argument /// deduction. @@ -4761,7 +5266,7 @@ public: /// FIXME: Serialize this structure to the AST file. llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> > SuppressedDiagnostics; - + /// \brief A stack object to be created when performing template /// instantiation. /// @@ -4863,15 +5368,15 @@ public: }; void PrintInstantiationStack(); - + /// \brief Determines whether we are currently in a context where /// template argument substitution failures are not considered /// errors. /// /// \returns An empty \c llvm::Optional if we're not in a SFINAE context. - /// Otherwise, contains a pointer that, if non-NULL, contains the nearest - /// template-deduction context object, which can be used to capture - /// diagnostics that will be suppressed. + /// Otherwise, contains a pointer that, if non-NULL, contains the nearest + /// template-deduction context object, which can be used to capture + /// diagnostics that will be suppressed. llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; /// \brief RAII class used to determine whether SFINAE has @@ -4882,22 +5387,22 @@ public: unsigned PrevSFINAEErrors; bool PrevInNonInstantiationSFINAEContext; bool PrevAccessCheckingSFINAE; - + public: explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), PrevInNonInstantiationSFINAEContext( SemaRef.InNonInstantiationSFINAEContext), PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE) - { + { if (!SemaRef.isSFINAEContext()) SemaRef.InNonInstantiationSFINAEContext = true; SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE; } - ~SFINAETrap() { - SemaRef.NumSFINAEErrors = PrevSFINAEErrors; - SemaRef.InNonInstantiationSFINAEContext + ~SFINAETrap() { + SemaRef.NumSFINAEErrors = PrevSFINAEErrors; + SemaRef.InNonInstantiationSFINAEContext = PrevInNonInstantiationSFINAEContext; SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; } @@ -4917,7 +5422,7 @@ public: typedef llvm::DenseMap<IdentifierInfo *, TypoCorrection> UnqualifiedTyposCorrectedMap; - + /// \brief A cache containing the results of typo correction for unqualified /// name lookup. /// @@ -4925,7 +5430,7 @@ public: /// there was no correction), while the boolean will be true when the /// string represents a keyword. UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected; - + /// \brief Worker object for performing CFG-based warnings. sema::AnalysisBasedWarnings AnalysisWarnings; @@ -4973,15 +5478,16 @@ public: ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions); - bool SubstParmTypes(SourceLocation Loc, + llvm::Optional<unsigned> NumExpansions, + bool ExpectParameterPack); + bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<QualType> &ParamTypes, SmallVectorImpl<ParmVarDecl *> *OutParams = 0); ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); - + /// \brief Substitute the given template arguments into a list of /// expressions, expanding pack expansions if required. /// @@ -5007,6 +5513,10 @@ public: Decl *SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs); + ExprResult SubstInitializer(Expr *E, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit); + bool SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, @@ -5019,8 +5529,27 @@ public: TemplateSpecializationKind TSK, bool Complain = true); + bool InstantiateEnum(SourceLocation PointOfInstantiation, + EnumDecl *Instantiation, EnumDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK); + + struct LateInstantiatedAttribute { + const Attr *TmplAttr; + LocalInstantiationScope *Scope; + Decl *NewDecl; + + LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S, + Decl *D) + : TmplAttr(A), Scope(S), NewDecl(D) + { } + }; + typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec; + void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst); + const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs = 0, + LocalInstantiationScope *OuterMostScope = 0); bool InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, @@ -5046,7 +5575,7 @@ public: SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); TemplateName - SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, + SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs); bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, @@ -5066,11 +5595,6 @@ public: void InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); - bool InstantiateInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation &LParenLoc, - ASTOwningVector<Expr*> &NewArgs, - SourceLocation &RParenLoc); NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -5078,6 +5602,17 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs); // Objective-C declarations. + enum ObjCContainerKind { + OCK_None = -1, + OCK_Interface = 0, + OCK_Protocol, + OCK_Category, + OCK_ClassExtension, + OCK_Implementation, + OCK_CategoryImplementation + }; + ObjCContainerKind getObjCContainerKind() const; + Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, @@ -5129,12 +5664,15 @@ public: IdentifierInfo *CatName, SourceLocation CatLoc); + DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, + ArrayRef<Decl *> Decls); + DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, unsigned NumElts); - Decl *ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, const IdentifierLocPair *IdentList, unsigned NumElts, AttributeList *attrList); @@ -5155,7 +5693,7 @@ public: /// setters and getters as needed. /// \param property The property declaration being processed /// \param DC The semantic container for the property - /// \param redeclaredProperty Declaration for property if redeclared + /// \param redeclaredProperty Declaration for property if redeclared /// in class extension. /// \param lexicalDC Container for redeclaredProperty. void ProcessPropertyDecl(ObjCPropertyDecl *property, @@ -5180,12 +5718,13 @@ public: void MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl); - void ActOnAtEnd(Scope *S, SourceRange AtEnd, - Decl **allMethods = 0, unsigned allNum = 0, - Decl **allProperties = 0, unsigned pNum = 0, - DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0); + Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd, + Decl **allMethods = 0, unsigned allNum = 0, + Decl **allProperties = 0, unsigned pNum = 0, + DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0); Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, bool *OverridingProperty, @@ -5246,9 +5785,11 @@ public: ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, bool IsInstance); + ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, + bool IsInstance); bool inferObjCARCLifetime(ValueDecl *decl); - + ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, @@ -5264,7 +5805,7 @@ public: SourceLocation receiverNameLoc, SourceLocation propertyNameLoc); - ObjCMethodDecl *tryCaptureObjCSelf(); + ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); /// \brief Describes the kind of message expression indicated by a message /// send that starts with an identifier. @@ -5277,7 +5818,7 @@ public: /// name. ObjCClassMessage }; - + ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, SourceLocation NameLoc, @@ -5300,7 +5841,15 @@ public: SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc, - MultiExprArg Args); + MultiExprArg Args, + bool isImplicit = false); + + ExprResult BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args); ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, @@ -5318,7 +5867,15 @@ public: SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc, - MultiExprArg Args); + MultiExprArg Args, + bool isImplicit = false); + + ExprResult BuildInstanceMessageImplicit(Expr *Receiver, + QualType ReceiverType, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args); ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, @@ -5333,7 +5890,7 @@ public: SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo, Expr *SubExpr); - + ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc, ObjCBridgeCastKind Kind, @@ -5341,19 +5898,19 @@ public: ParsedType Type, SourceLocation RParenLoc, Expr *SubExpr); - + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); - + /// \brief Check whether the given new method is a valid override of the /// given overridden method, and set any properties that should be inherited. - void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, const ObjCMethodDecl *Overridden, bool IsImplementation); /// \brief Check whether the given method overrides any methods in its class, /// calling \c CheckObjCMethodOverride for each overridden method. bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC); - + enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural @@ -5387,7 +5944,7 @@ public: SourceLocation PragmaLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); - + /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); @@ -5397,7 +5954,7 @@ public: SourceLocation PragmaLoc); /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... . - void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, + void ActOnPragmaVisibility(const IdentifierInfo* VisType, SourceLocation PragmaLoc); NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, @@ -5409,6 +5966,14 @@ public: SourceLocation PragmaLoc, SourceLocation WeakNameLoc); + /// ActOnPragmaRedefineExtname - Called on well formed + /// #pragma redefine_extname oldname newname. + void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc); + /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, IdentifierInfo* AliasName, @@ -5432,7 +5997,8 @@ public: /// PushNamespaceVisibilityAttr - Note that we've entered a /// namespace with a visibility attribute. - void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr); + void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, + SourceLocation Loc); /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used, /// add an appropriate visibility attribute. @@ -5440,7 +6006,7 @@ public: /// PopPragmaVisibility - Pop the top element of the visibility stack; used /// for '#pragma GCC visibility' and visibility attributes on namespaces. - void PopPragmaVisibility(); + void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc); /// FreeVisContext - Deallocate and null out VisContext. void FreeVisContext(); @@ -5472,7 +6038,7 @@ public: ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK = VK_RValue, const CXXCastPath *BasePath = 0, - CheckedConversionKind CCK + CheckedConversionKind CCK = CCK_ImplicitConversion); /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding @@ -5525,7 +6091,8 @@ public: unsigned FirstProtoArg, Expr **Args, unsigned NumArgs, SmallVector<Expr *, 8> &AllArgs, - VariadicCallType CallType = VariadicDoesNotApply); + VariadicCallType CallType = VariadicDoesNotApply, + bool AllowExplicit = false); // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will warn if the resulting type is not a POD type. @@ -5566,9 +6133,9 @@ public: IncompatiblePointer, /// IncompatiblePointer - The assignment is between two pointers types which - /// point to integers which have a different sign, but are otherwise identical. - /// This is a subset of the above, but broken out because it's by far the most - /// common case of incompatible pointers. + /// point to integers which have a different sign, but are otherwise + /// identical. This is a subset of the above, but broken out because it's by + /// far the most common case of incompatible pointers. IncompatiblePointerSign, /// CompatiblePointerDiscardsQualifiers - The assignment discards @@ -5652,13 +6219,11 @@ public: ExprResult PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, - bool AllowExplicit = false, - bool Diagnose = true); + bool AllowExplicit = false); ExprResult PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit, - ImplicitConversionSequence& ICS, - bool Diagnose = true); + ImplicitConversionSequence& ICS); ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence& ICS, AssignmentAction Action, @@ -5685,7 +6250,7 @@ public: ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign = false); QualType CheckAdditionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, QualType* CompLHSTy = 0); QualType CheckSubtractionOperands( // C99 6.5.6 ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, @@ -5706,11 +6271,15 @@ public: // For compound assignment, pass both expressions and the converted type. QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType); - - void ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, - QualType& LHSTy); - ExprResult ConvertPropertyForRValue(Expr *E); - + + ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opcode, Expr *Op); + ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opcode, + Expr *LHS, Expr *RHS); + ExprResult checkPseudoObjectRValue(Expr *E); + Expr *recreateSyntacticForm(PseudoObjectExpr *E); + QualType CheckConditionalOperands( // C99 6.5.15 ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc); @@ -5719,10 +6288,12 @@ public: ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool *NonStandardCompositeType = 0); - QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, ExprResult &E2, + QualType FindCompositePointerType(SourceLocation Loc, + ExprResult &E1, ExprResult &E2, bool *NonStandardCompositeType = 0) { Expr *E1Tmp = E1.take(), *E2Tmp = E2.take(); - QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, NonStandardCompositeType); + QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, + NonStandardCompositeType); E1 = Owned(E1Tmp); E2 = Owned(E2Tmp); return Composite; @@ -5737,8 +6308,11 @@ public: /// type checking for vector binary operators. QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign); + QualType GetSignedVectorType(QualType V); QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool isRelational); + QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc); /// type checking declaration initializers (C99 6.7.8) bool CheckForConstantInitializer(Expr *e, QualType t); @@ -5776,6 +6350,10 @@ public: Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path); + /// \brief Force an expression with unknown-type to an expression of the + /// given type. + ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); + // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size. @@ -5796,11 +6374,17 @@ public: Expr *CastExpr, SourceLocation RParenLoc); + enum ARCConversionResult { ACR_okay, ACR_unbridged }; + /// \brief Checks for invalid conversions and casts between /// retainable pointers and other pointer kinds. - void CheckObjCARCConversion(SourceRange castRange, QualType castType, - Expr *&op, CheckedConversionKind CCK); - + ARCConversionResult CheckObjCARCConversion(SourceRange castRange, + QualType castType, Expr *&op, + CheckedConversionKind CCK); + + Expr *stripARCUnbridgedCast(Expr *e); + void diagnoseARCUnbridgedCast(Expr *e); + bool CheckObjCARCUnavailableWeakConversion(QualType castType, QualType ExprType); @@ -5838,7 +6422,7 @@ public: /// \brief If the given expression involves a message send to a method /// with a related result type, emit a note describing what happened. void EmitRelatedResultTypeNote(const Expr *E); - + /// CheckBooleanCondition - Diagnose problems involving the use of /// the given expression as a boolean condition (e.g. in an if /// statement). Also performs the standard function and array @@ -5851,7 +6435,7 @@ public: ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, Expr *SubExpr); - + /// DiagnoseAssignmentAsCondition - Given that an expression is /// being used as a boolean condition, warn if it's an assignment. void DiagnoseAssignmentAsCondition(Expr *E); @@ -5875,18 +6459,28 @@ public: /// in the global scope. bool CheckObjCDeclScope(Decl *D); - /// VerifyIntegerConstantExpression - verifies that an expression is an ICE, + /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE, /// and reports the appropriate diagnostics. Returns false on success. /// Can optionally return the value of the expression. - bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic Diag, + bool AllowFold, + PartialDiagnostic FoldDiag); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic Diag, + bool AllowFold = true) { + return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold, + PDiag(0)); + } + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result = 0); /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. /// Returns false on success. /// Can optionally return whether the bit-field is of width 0 - bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth, - bool *ZeroWidth = 0); + ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, Expr *BitWidth, + bool *ZeroWidth = 0); enum CUDAFunctionTarget { CFT_Device, @@ -5939,7 +6533,7 @@ public: /// \brief Code completion occurs within the condition of an if, /// while, switch, or for statement. PCC_Condition, - /// \brief Code completion occurs within the body of a function on a + /// \brief Code completion occurs within the body of a function on a /// recovery path, where we do not have a specific handle on our position /// in the grammar. PCC_RecoveryInFunction, @@ -5948,19 +6542,20 @@ public: /// \brief Code completion occurs in a parenthesized expression, which /// might also be a type cast. PCC_ParenthesizedExpression, - /// \brief Code completion occurs within a sequence of declaration + /// \brief Code completion occurs within a sequence of declaration /// specifiers within a function, method, or block. PCC_LocalDeclarationSpecifiers }; + void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); void CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext); void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, bool AllowNestedNameSpecifiers); - + struct CodeCompleteExpressionData; - void CodeCompleteExpression(Scope *S, + void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, @@ -5969,12 +6564,12 @@ public: void CodeCompleteTag(Scope *S, unsigned TagSpec); void CodeCompleteTypeQualifiers(DeclSpec &DS); void CodeCompleteCase(Scope *S); - void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs); + void CodeCompleteCall(Scope *S, Expr *Fn, llvm::ArrayRef<Expr *> Args); void CodeCompleteInitializer(Scope *S, Decl *D); void CodeCompleteReturn(Scope *S); void CodeCompleteAfterIf(Scope *S); void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS); - + void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext); void CodeCompleteUsing(Scope *S); @@ -5985,7 +6580,9 @@ public: void CodeCompleteConstructorInitializer(Decl *Constructor, CXXCtorInitializer** Initializers, unsigned NumInitializers); - + void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, + bool AfterAmpersand); + void CodeCompleteObjCAtDirective(Scope *S); void CodeCompleteObjCAtVisibility(Scope *S); void CodeCompleteObjCAtStatement(Scope *S); @@ -5993,7 +6590,7 @@ public: void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); void CodeCompleteObjCPropertyGetter(Scope *S); void CodeCompleteObjCPropertySetter(Scope *S); - void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, bool IsParameter); void CodeCompleteObjCMessageReceiver(Scope *S); void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, @@ -6010,7 +6607,7 @@ public: unsigned NumSelIdents, bool AtArgumentExpression, ObjCInterfaceDecl *Super = 0); - void CodeCompleteObjCForCollection(Scope *S, + void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); void CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, @@ -6035,7 +6632,7 @@ public: void CodeCompleteObjCMethodDecl(Scope *S, bool IsInstanceMethod, ParsedType ReturnType); - void CodeCompleteObjCMethodDeclSelector(Scope *S, + void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnType, @@ -6051,6 +6648,7 @@ public: unsigned Argument); void CodeCompleteNaturalLanguage(); void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, SmallVectorImpl<CodeCompletionResult> &Results); //@} @@ -6061,14 +6659,16 @@ public: SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, unsigned ByteNo) const; -private: +private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, - bool isSubscript=false, bool AllowOnePastEnd=true); + const ArraySubscriptExpr *ASE=0, + bool AllowOnePastEnd=true, bool IndexNegated=false); void CheckArrayAccess(const Expr *E); bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); + bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, + Expr **Args, unsigned NumArgs); bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); - bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall); bool CheckObjCString(Expr *Arg); ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); @@ -6092,43 +6692,49 @@ private: bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); - bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, + enum FormatStringType { + FST_Scanf, + FST_Printf, + FST_NSString, + FST_Strftime, + FST_Strfmon, + FST_Kprintf, + FST_Unknown + }; + static FormatStringType GetFormatStringType(const FormatAttr *Format); + bool SemaCheckStringLiteral(const Expr *E, Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, - unsigned firstDataArg, bool isPrintf); + unsigned firstDataArg, FormatStringType Type, + bool inFunctionCall = true); void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, - const CallExpr *TheCall, bool HasVAListArg, + Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, - bool isPrintf); + FormatStringType Type, bool inFunctionCall); + + void CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall); + void CheckFormatArguments(const FormatAttr *Format, Expr **Args, + unsigned NumArgs, bool IsCXXMember, + SourceLocation Loc, SourceRange Range); + void CheckFormatArguments(Expr **Args, unsigned NumArgs, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + SourceLocation Loc, SourceRange range); void CheckNonNullArguments(const NonNullAttr *NonNull, const Expr * const *ExprArgs, SourceLocation CallSiteLoc); - void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg, - bool isPrintf); - - /// \brief Enumeration used to describe which of the memory setting or copying - /// functions is being checked by \c CheckMemaccessArguments(). - enum CheckedMemoryFunction { - CMF_Memset, - CMF_Memcpy, - CMF_Memmove, - CMF_Memcmp, - CMF_Strncpy, - CMF_Strncmp, - CMF_Strncasecmp, - CMF_Strncat, - CMF_Strndup - }; - - void CheckMemaccessArguments(const CallExpr *Call, CheckedMemoryFunction CMF, + void CheckMemaccessArguments(const CallExpr *Call, + unsigned BId, IdentifierInfo *FnName); void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName); + void CheckStrncatArguments(const CallExpr *Call, + IdentifierInfo *FnName); + void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc); void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); @@ -6141,13 +6747,13 @@ private: /// /// The parser maintains this state here. Scope *CurScope; - + protected: friend class Parser; - friend class InitializationSequence; + friend class InitializationSequence; friend class ASTReader; friend class ASTWriter; - + public: /// \brief Retrieve the parser's current scope. /// @@ -6158,7 +6764,7 @@ public: /// itself and in routines directly invoked from the parser and *never* from /// template substitution or instantiation. Scope *getCurScope() const { return CurScope; } - + Decl *getObjCDeclContext() const; DeclContext *getCurLexicalContext() const { @@ -6174,9 +6780,12 @@ class EnterExpressionEvaluationContext { public: EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext) + Sema::ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = 0, + bool IsDecltype = false) : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext); + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, + IsDecltype); } ~EnterExpressionEvaluationContext() { diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h index 3689a6e..139cce8 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h @@ -24,6 +24,7 @@ namespace clang { /// clients that read ASTs and then require further semantic /// analysis of the entities in those ASTs. class SemaConsumer : public ASTConsumer { + virtual void anchor(); public: SemaConsumer() { ASTConsumer::SemaConsumer = true; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h index 2c4bf4b..9605bf8 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define SEMASTART #include "clang/Basic/DiagnosticSemaKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h index 0c1bba5..fffca67 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h @@ -39,7 +39,7 @@ struct ConversionFixItGenerator { ExprValueKind FromVK); /// The list of Hints generated so far. - SmallVector<FixItHint, 1> Hints; + std::vector<FixItHint> Hints; /// The number of Conversions fixed. This can be different from the size /// of the Hints vector since we allow multiple FixIts per conversion. diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h index 78f50fa..c16823a 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Template.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h @@ -268,6 +268,50 @@ namespace clang { Exited = true; } + /// \brief Clone this scope, and all outer scopes, down to the given + /// outermost scope. + LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { + if (this == Outermost) return this; + LocalInstantiationScope *newScope = + new LocalInstantiationScope(SemaRef, CombineWithOuterScope); + + newScope->Outer = 0; + if (Outer) + newScope->Outer = Outer->cloneScopes(Outermost); + + newScope->PartiallySubstitutedPack = PartiallySubstitutedPack; + newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack; + newScope->NumArgsInPartiallySubstitutedPack = + NumArgsInPartiallySubstitutedPack; + + for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end(); + I != E; ++I) { + const Decl *D = I->first; + llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = + newScope->LocalDecls[D]; + if (I->second.is<Decl *>()) { + Stored = I->second.get<Decl *>(); + } else { + DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); + DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); + Stored = NewPack; + newScope->ArgumentPacks.push_back(NewPack); + } + } + return newScope; + } + + /// \brief deletes the given scope, and all otuer scopes, down to the + /// given outermost scope. + static void deleteScopes(LocalInstantiationScope *Scope, + LocalInstantiationScope *Outermost) { + while (Scope && Scope != Outermost) { + LocalInstantiationScope *Out = Scope->Outer; + delete Scope; + Scope = Out; + } + } + /// \brief Find the instantiation of the declaration D within the current /// instantiation scope. /// @@ -314,6 +358,8 @@ namespace clang { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; DeclContext *Owner; const MultiLevelTemplateArgumentList &TemplateArgs; + Sema::LateInstantiatedAttrVec* LateAttrs; + LocalInstantiationScope *StartingScope; /// \brief A list of out-of-line class template partial /// specializations that will need to be instantiated after the @@ -326,7 +372,7 @@ namespace clang { TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner), - TemplateArgs(TemplateArgs) { } + TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { } // FIXME: Once we get closer to completion, replace these manually-written // declarations with automatically-generated ones from @@ -382,6 +428,21 @@ namespace clang { return 0; } + // Enable late instantiation of attributes. Late instantiated attributes + // will be stored in LA. + void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) { + LateAttrs = LA; + StartingScope = SemaRef.CurrentInstantiationScope; + } + + // Disable late instantiation of attributes. + void disableLateAttributeInstantiation() { + LateAttrs = 0; + StartingScope = 0; + } + + LocalInstantiationScope *getStartingScope() const { return StartingScope; } + typedef SmallVectorImpl<std::pair<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> > @@ -423,6 +484,7 @@ namespace clang { InstantiateClassTemplatePartialSpecialization( ClassTemplateDecl *ClassTemplate, ClassTemplatePartialSpecializationDecl *PartialSpec); + void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern); }; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h index 690129a..100d56e 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h @@ -23,7 +23,7 @@ class ASTContext; class TemplateArgumentList; namespace sema { - + /// \brief Provides information about an attempted template argument /// deduction, whose success or failure was described by a /// TemplateDeductionResult value. @@ -39,10 +39,10 @@ class TemplateDeductionInfo { /// deduction is occurring. SourceLocation Loc; - /// \brief Warnings (and follow-on notes) that were suppressed due to + /// \brief Warnings (and follow-on notes) that were suppressed due to /// SFINAE while performing template argument deduction. SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; - + // do not implement these TemplateDeductionInfo(const TemplateDeductionInfo&); TemplateDeductionInfo &operator=(const TemplateDeductionInfo&); @@ -75,23 +75,24 @@ public: Deduced = NewDeduced; } - /// \brief Add a new diagnostic to the set of diagnostics - void addSuppressedDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) { + /// \brief Add a new diagnostic to the set of diagnostics + void addSuppressedDiagnostic(SourceLocation Loc, + const PartialDiagnostic &PD) { SuppressedDiagnostics.push_back(std::make_pair(Loc, PD)); } - + /// \brief Iterator over the set of suppressed diagnostics. - typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator + typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator diag_iterator; - + /// \brief Returns an iterator at the beginning of the sequence of suppressed /// diagnostics. diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); } - + /// \brief Returns an iterator at the end of the sequence of suppressed /// diagnostics. diag_iterator diag_end() const { return SuppressedDiagnostics.end(); } - + /// \brief The template parameter to which a template argument /// deduction failure refers. /// diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h index 9537c30..a8f6e11 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h @@ -23,32 +23,46 @@ namespace clang { /// @brief Simple class containing the result of Sema::CorrectTypo class TypoCorrection { public: + // "Distance" for unusable corrections + static const unsigned InvalidDistance = ~0U; + // The largest distance still considered valid (larger edit distances are + // mapped to InvalidDistance by getEditDistance). + static const unsigned MaximumDistance = 10000U; + + // Relative weightings of the "edit distance" components. The higher the + // weight, the more of a penalty to fitness the component will give (higher + // weights mean greater contribution to the total edit distance, with the + // best correction candidates having the lowest edit distance). + static const unsigned CharDistanceWeight = 100U; + static const unsigned QualifierDistanceWeight = 110U; + static const unsigned CallbackDistanceWeight = 150U; + TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl, - NestedNameSpecifier *NNS=0, unsigned distance=0) - : CorrectionName(Name), - CorrectionNameSpec(NNS), - EditDistance(distance) { + NestedNameSpecifier *NNS=0, unsigned CharDistance=0, + unsigned QualifierDistance=0) + : CorrectionName(Name), CorrectionNameSpec(NNS), + CharDistance(CharDistance), QualifierDistance(QualifierDistance), + CallbackDistance(0) { if (NameDecl) CorrectionDecls.push_back(NameDecl); } TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0, - unsigned distance=0) - : CorrectionName(Name->getDeclName()), - CorrectionNameSpec(NNS), - EditDistance(distance) { + unsigned CharDistance=0) + : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), + CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) { if (Name) CorrectionDecls.push_back(Name); } TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0, - unsigned distance=0) - : CorrectionName(Name), - CorrectionNameSpec(NNS), - EditDistance(distance) {} + unsigned CharDistance=0) + : CorrectionName(Name), CorrectionNameSpec(NNS), + CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) {} TypoCorrection() - : CorrectionNameSpec(0), EditDistance(0) {} + : CorrectionNameSpec(0), CharDistance(0), QualifierDistance(0), + CallbackDistance(0) {} /// \brief Gets the DeclarationName of the typo correction DeclarationName getCorrection() const { return CorrectionName; } @@ -64,8 +78,41 @@ public: CorrectionNameSpec = NNS; } - /// \brief Gets the "edit distance" of the typo correction from the typo - unsigned getEditDistance() const { return EditDistance; } + void setQualifierDistance(unsigned ED) { + QualifierDistance = ED; + } + + void setCallbackDistance(unsigned ED) { + CallbackDistance = ED; + } + + // Convert the given weighted edit distance to a roughly equivalent number of + // single-character edits (typically for comparison to the length of the + // string being edited). + static unsigned NormalizeEditDistance(unsigned ED) { + if (ED > MaximumDistance) + return InvalidDistance; + return (ED + CharDistanceWeight / 2) / CharDistanceWeight; + } + + /// \brief Gets the "edit distance" of the typo correction from the typo. + /// If Normalized is true, scale the distance down by the CharDistanceWeight + /// to return the edit distance in terms of single-character edits. + unsigned getEditDistance(bool Normalized = true) const { + if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance || + CallbackDistance > MaximumDistance) + return InvalidDistance; + unsigned ED = + CharDistance * CharDistanceWeight + + QualifierDistance * QualifierDistanceWeight + + CallbackDistance * CallbackDistanceWeight; + if (ED > MaximumDistance) + return InvalidDistance; + // Half the CharDistanceWeight is added to ED to simulate rounding since + // integer division truncates the value (i.e. round-to-nearest-int instead + // of round-to-zero). + return Normalized ? NormalizeEditDistance(ED) : ED; + } /// \brief Gets the pointer to the declaration of the typo correction NamedDecl* getCorrectionDecl() const { @@ -110,6 +157,12 @@ public: CorrectionDecls.front() == 0; } + // Check if this TypoCorrection is the given keyword. + template<std::size_t StrLen> + bool isKeyword(const char (&Str)[StrLen]) const { + return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str); + } + // Returns true if the correction either is a keyword or has a known decl. bool isResolved() const { return !CorrectionDecls.empty(); } @@ -122,6 +175,11 @@ public: return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); } decl_iterator end() { return CorrectionDecls.end(); } + typedef llvm::SmallVector<NamedDecl*, 1>::const_iterator const_decl_iterator; + const_decl_iterator begin() const { + return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); + } + const_decl_iterator end() const { return CorrectionDecls.end(); } private: bool hasCorrectionDecl() const { @@ -132,7 +190,65 @@ private: DeclarationName CorrectionName; NestedNameSpecifier *CorrectionNameSpec; llvm::SmallVector<NamedDecl*, 1> CorrectionDecls; - unsigned EditDistance; + unsigned CharDistance; + unsigned QualifierDistance; + unsigned CallbackDistance; +}; + +/// @brief Base class for callback objects used by Sema::CorrectTypo to check +/// the validity of a potential typo correction. +class CorrectionCandidateCallback { + public: + static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; + + CorrectionCandidateCallback() + : WantTypeSpecifiers(true), WantExpressionKeywords(true), + WantCXXNamedCasts(true), WantRemainingKeywords(true), + WantObjCSuper(false), + IsObjCIvarLookup(false) {} + + virtual ~CorrectionCandidateCallback() {} + + /// \brief Simple predicate used by the default RankCandidate to + /// determine whether to return an edit distance of 0 or InvalidDistance. + /// This can be overrided by validators that only need to determine if a + /// candidate is viable, without ranking potentially viable candidates. + /// Only ValidateCandidate or RankCandidate need to be overriden by a + /// callback wishing to check the viability of correction candidates. + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return true; + } + + /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank + /// to a candidate (where a lower value represents a better candidate), or + /// returning InvalidDistance if the candidate is not at all viable. For + /// validation callbacks that only need to determine if a candidate is viable, + /// the default RankCandidate returns either 0 or InvalidDistance depending + /// whether ValidateCandidate returns true or false. + virtual unsigned RankCandidate(const TypoCorrection &candidate) { + return ValidateCandidate(candidate) ? 0 : InvalidDistance; + } + + // Flags for context-dependent keywords. + // TODO: Expand these to apply to non-keywords or possibly remove them. + bool WantTypeSpecifiers; + bool WantExpressionKeywords; + bool WantCXXNamedCasts; + bool WantRemainingKeywords; + bool WantObjCSuper; + // Temporary hack for the one case where a CorrectTypoContext enum is used + // when looking up results. + bool IsObjCIvarLookup; +}; + +/// @brief Simple template class for restricting typo correction candidates +/// to ones having a single Decl* of the given type. +template <class C> +class DeclFilterCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return candidate.getCorrectionDeclAs<C>(); + } }; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h index 494835c..4591630 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h @@ -127,7 +127,7 @@ namespace clang { /// \brief The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; - /// \brief An ID number that refers to an ObjC selctor in an AST file. + /// \brief An ID number that refers to an ObjC selector in an AST file. typedef uint32_t SelectorID; /// \brief The number of predefined selector IDs. @@ -141,6 +141,12 @@ namespace clang { /// preprocessing record. typedef uint32_t PreprocessedEntityID; + /// \brief An ID number that refers to a submodule in a module file. + typedef uint32_t SubmoduleID; + + /// \brief The number of predefined submodule IDs. + const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1; + /// \brief Source range/offset of a preprocessed entity. struct PPEntityOffset { /// \brief Raw source location of beginning of range. @@ -156,6 +162,22 @@ namespace clang { BitOffset(BitOffset) { } }; + /// \brief Source range/offset of a preprocessed entity. + struct DeclOffset { + /// \brief Raw source location. + unsigned Loc; + /// \brief Offset in the AST file. + uint32_t BitOffset; + + DeclOffset() : Loc(0), BitOffset(0) { } + DeclOffset(SourceLocation Loc, uint32_t BitOffset) + : Loc(Loc.getRawEncoding()), + BitOffset(BitOffset) { } + void setLocation(SourceLocation L) { + Loc = L.getRawEncoding(); + } + }; + /// \brief The number of predefined preprocessed entity IDs. const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1; @@ -182,7 +204,10 @@ namespace clang { DECL_UPDATES_BLOCK_ID, /// \brief The block containing the detailed preprocessing record. - PREPROCESSOR_DETAIL_BLOCK_ID + PREPROCESSOR_DETAIL_BLOCK_ID, + + /// \brief The block containing the submodule structure. + SUBMODULE_BLOCK_ID }; /// \brief Record types that occur within the AST block itself. @@ -341,10 +366,11 @@ namespace clang { /// \brief Record code for an update to the TU's lexically contained /// declarations. TU_UPDATE_LEXICAL = 28, - - /// \brief Record code for an update to first decls pointing to the - /// latest redeclarations. - REDECLS_UPDATE_LATEST = 29, + + /// \brief Record code for the array describing the locations (in the + /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by + /// the first known ID. + LOCAL_REDECLARATIONS_MAP = 29, /// \brief Record code for declarations that Sema keeps references of. SEMA_DECL_REFS = 30, @@ -418,9 +444,32 @@ namespace clang { /// which stores information about #line directives. SOURCE_MANAGER_LINE_TABLE = 48, - /// \brief Record code for ObjC categories in a module that are chained to - /// an interface. - OBJC_CHAINED_CATEGORIES + /// \brief Record code for map of Objective-C class definition IDs to the + /// ObjC categories in a module that are attached to that class. + OBJC_CATEGORIES_MAP = 49, + + /// \brief Record code for a file sorted array of DeclIDs in a module. + FILE_SORTED_DECLS = 50, + + /// \brief Record code for an array of all of the (sub)modules that were + /// imported by the AST file. + IMPORTED_MODULES = 51, + + /// \brief Record code for the set of merged declarations in an AST file. + MERGED_DECLARATIONS = 52, + + /// \brief Record code for the array of redeclaration chains. + /// + /// This array can only be interpreted properly using the local + /// redeclarations map. + LOCAL_REDECLARATIONS = 53, + + /// \brief Record code for the array of Objective-C categories (including + /// extensions). + /// + /// This array can only be interpreted properly using the Objective-C + /// categories map. + OBJC_CATEGORIES }; /// \brief Record types used within a source manager block. @@ -433,7 +482,8 @@ namespace clang { SM_SLOC_BUFFER_ENTRY = 2, /// \brief Describes a blob that contains the data for a buffer /// entry. This kind of record always directly follows a - /// SM_SLOC_BUFFER_ENTRY record. + /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an + /// overridden buffer. SM_SLOC_BUFFER_BLOB = 3, /// \brief Describes a source location entry (SLocEntry) for a /// macro expansion. @@ -472,6 +522,30 @@ namespace clang { PPD_INCLUSION_DIRECTIVE = 2 }; + /// \brief Record types used within a submodule description block. + enum SubmoduleRecordTypes { + /// \brief Metadata for submodules as a whole. + SUBMODULE_METADATA = 0, + /// \brief Defines the major attributes of a submodule, including its + /// name and parent. + SUBMODULE_DEFINITION = 1, + /// \brief Specifies the umbrella header used to create this module, + /// if any. + SUBMODULE_UMBRELLA_HEADER = 2, + /// \brief Specifies a header that falls into this (sub)module. + SUBMODULE_HEADER = 3, + /// \brief Specifies an umbrella directory. + SUBMODULE_UMBRELLA_DIR = 4, + /// \brief Specifies the submodules that are imported by this + /// submodule. + SUBMODULE_IMPORTS = 5, + /// \brief Specifies the submodules that are re-exported from this + /// submodule. + SUBMODULE_EXPORTS = 6, + /// \brief Specifies a required feature. + SUBMODULE_REQUIRES = 7 + }; + /// \defgroup ASTAST AST file AST constants /// /// The constants in this group describe various components of the @@ -554,7 +628,11 @@ namespace clang { /// \brief The "auto &&" deduction type. PREDEF_TYPE_AUTO_RREF_DEDUCT = 32, /// \brief The OpenCL 'half' / ARM NEON __fp16 type. - PREDEF_TYPE_HALF_ID = 33 + PREDEF_TYPE_HALF_ID = 33, + /// \brief ARC's unbridged-cast placeholder type. + PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, + /// \brief The pseudo-object placeholder type. + PREDEF_TYPE_PSEUDO_OBJECT = 35 }; /// \brief The number of predefined type IDs that are reserved for @@ -662,28 +740,26 @@ namespace clang { enum SpecialTypeIDs { /// \brief __builtin_va_list SPECIAL_TYPE_BUILTIN_VA_LIST = 0, - /// \brief Objective-C Protocol type - SPECIAL_TYPE_OBJC_PROTOCOL = 1, /// \brief CFConstantString type - SPECIAL_TYPE_CF_CONSTANT_STRING = 2, + SPECIAL_TYPE_CF_CONSTANT_STRING = 1, /// \brief C FILE typedef type - SPECIAL_TYPE_FILE = 3, + SPECIAL_TYPE_FILE = 2, /// \brief C jmp_buf typedef type - SPECIAL_TYPE_jmp_buf = 4, + SPECIAL_TYPE_JMP_BUF = 3, /// \brief C sigjmp_buf typedef type - SPECIAL_TYPE_sigjmp_buf = 5, + SPECIAL_TYPE_SIGJMP_BUF = 4, /// \brief Objective-C "id" redefinition type - SPECIAL_TYPE_OBJC_ID_REDEFINITION = 6, + SPECIAL_TYPE_OBJC_ID_REDEFINITION = 5, /// \brief Objective-C "Class" redefinition type - SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 7, + SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 6, /// \brief Objective-C "SEL" redefinition type - SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 8, + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 7, /// \brief C ucontext_t typedef type - SPECIAL_TYPE_UCONTEXT_T = 9 + SPECIAL_TYPE_UCONTEXT_T = 8 }; /// \brief The number of special type IDs. - const unsigned NumSpecialTypeIDs = 0; + const unsigned NumSpecialTypeIDs = 9; /// \brief Predefined declaration IDs. /// @@ -706,22 +782,25 @@ namespace clang { /// \brief The Objective-C 'Class' type. PREDEF_DECL_OBJC_CLASS_ID = 4, + + /// \brief The Objective-C 'Protocol' type. + PREDEF_DECL_OBJC_PROTOCOL_ID = 5, /// \brief The signed 128-bit integer type. - PREDEF_DECL_INT_128_ID = 5, + PREDEF_DECL_INT_128_ID = 6, /// \brief The unsigned 128-bit integer type. - PREDEF_DECL_UNSIGNED_INT_128_ID = 6, + PREDEF_DECL_UNSIGNED_INT_128_ID = 7, /// \brief The internal 'instancetype' typedef. - PREDEF_DECL_OBJC_INSTANCETYPE_ID = 7 + PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8 }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 8; + const unsigned int NUM_PREDEF_DECL_IDS = 9; /// \brief Record codes for each kind of declaration. /// @@ -752,10 +831,6 @@ namespace clang { DECL_OBJC_IVAR, /// \brief A ObjCAtDefsFieldDecl record. DECL_OBJC_AT_DEFS_FIELD, - /// \brief A ObjCClassDecl record. - DECL_OBJC_CLASS, - /// \brief A ObjCForwardProtocolDecl record. - DECL_OBJC_FORWARD_PROTOCOL, /// \brief A ObjCCategoryDecl record. DECL_OBJC_CATEGORY, /// \brief A ObjCCategoryImplDecl record. @@ -859,7 +934,9 @@ namespace clang { DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK, /// \brief A ClassScopeFunctionSpecializationDecl record a class scope /// function specialization. (Microsoft extension). - DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION + DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, + /// \brief An ImportDecl recording a module import. + DECL_IMPORT }; /// \brief Record codes for each kind of statement or expression. @@ -875,6 +952,8 @@ namespace clang { STMT_STOP = 100, /// \brief A NULL expression. STMT_NULL_PTR, + /// \brief A reference to a previously [de]serialized Stmt record. + STMT_REF_PTR, /// \brief A NullStmt record. STMT_NULL, /// \brief A CompoundStmt record. @@ -973,10 +1052,10 @@ namespace clang { EXPR_SHUFFLE_VECTOR, /// \brief BlockExpr EXPR_BLOCK, - /// \brief A BlockDeclRef record. - EXPR_BLOCK_DECL_REF, /// \brief A GenericSelectionExpr record. EXPR_GENERIC_SELECTION, + /// \brief A PseudoObjectExpr record. + EXPR_PSEUDO_OBJECT, /// \brief An AtomicExpr record. EXPR_ATOMIC, @@ -984,6 +1063,12 @@ namespace clang { /// \brief An ObjCStringLiteral record. EXPR_OBJC_STRING_LITERAL, + + EXPR_OBJC_NUMERIC_LITERAL, + EXPR_OBJC_ARRAY_LITERAL, + EXPR_OBJC_DICTIONARY_LITERAL, + + /// \brief An ObjCEncodeExpr record. EXPR_OBJC_ENCODE, /// \brief An ObjCSelectorExpr record. @@ -994,6 +1079,8 @@ namespace clang { EXPR_OBJC_IVAR_REF_EXPR, /// \brief An ObjCPropertyRefExpr record. EXPR_OBJC_PROPERTY_REF_EXPR, + /// \brief An ObjCSubscriptRefExpr record. + EXPR_OBJC_SUBSCRIPT_REF_EXPR, /// \brief UNUSED EXPR_OBJC_KVC_REF_EXPR, /// \brief An ObjCMessageExpr record. @@ -1017,6 +1104,8 @@ namespace clang { STMT_OBJC_AT_THROW, /// \brief An ObjCAutoreleasePoolStmt record. STMT_OBJC_AUTORELEASE_POOL, + /// \brief A ObjCBoolLiteralExpr record. + EXPR_OBJC_BOOL_LITERAL, // C++ @@ -1045,6 +1134,8 @@ namespace clang { EXPR_CXX_CONST_CAST, /// \brief A CXXFunctionalCastExpr record. EXPR_CXX_FUNCTIONAL_CAST, + /// \brief A UserDefinedLiteral record. + EXPR_USER_DEFINED_LITERAL, /// \brief A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr @@ -1075,6 +1166,7 @@ namespace clang { EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr + EXPR_TYPE_TRAIT, // TypeTraitExpr EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr EXPR_PACK_EXPANSION, // PackExpansionExpr @@ -1097,7 +1189,10 @@ namespace clang { STMT_SEH_TRY, // SEHTryStmt // ARC - EXPR_OBJC_BRIDGED_CAST // ObjCBridgedCastExpr + EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr + + STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt + EXPR_LAMBDA // LambdaExpr }; /// \brief The kinds of designators that can occur in a @@ -1123,6 +1218,58 @@ namespace clang { CTOR_INITIALIZER_INDIRECT_MEMBER }; + /// \brief Describes the redeclarations of a declaration. + struct LocalRedeclarationsInfo { + DeclID FirstID; // The ID of the first declaration + unsigned Offset; // Offset into the array of redeclaration chains. + + friend bool operator<(const LocalRedeclarationsInfo &X, + const LocalRedeclarationsInfo &Y) { + return X.FirstID < Y.FirstID; + } + + friend bool operator>(const LocalRedeclarationsInfo &X, + const LocalRedeclarationsInfo &Y) { + return X.FirstID > Y.FirstID; + } + + friend bool operator<=(const LocalRedeclarationsInfo &X, + const LocalRedeclarationsInfo &Y) { + return X.FirstID <= Y.FirstID; + } + + friend bool operator>=(const LocalRedeclarationsInfo &X, + const LocalRedeclarationsInfo &Y) { + return X.FirstID >= Y.FirstID; + } + }; + + /// \brief Describes the categories of an Objective-C class. + struct ObjCCategoriesInfo { + DeclID DefinitionID; // The ID of the definition + unsigned Offset; // Offset into the array of category lists. + + friend bool operator<(const ObjCCategoriesInfo &X, + const ObjCCategoriesInfo &Y) { + return X.DefinitionID < Y.DefinitionID; + } + + friend bool operator>(const ObjCCategoriesInfo &X, + const ObjCCategoriesInfo &Y) { + return X.DefinitionID > Y.DefinitionID; + } + + friend bool operator<=(const ObjCCategoriesInfo &X, + const ObjCCategoriesInfo &Y) { + return X.DefinitionID <= Y.DefinitionID; + } + + friend bool operator>=(const ObjCCategoriesInfo &X, + const ObjCCategoriesInfo &Y) { + return X.DefinitionID >= Y.DefinitionID; + } + }; + /// @} } } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h index 588fe0e..ab0d313 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h @@ -23,6 +23,7 @@ class Decl; class ASTReader; class QualType; class MacroDefinition; +class Module; class ASTDeserializationListener { protected: @@ -47,6 +48,11 @@ public: /// \brief A macro definition was read from the AST file. virtual void MacroDefinitionRead(serialization::PreprocessedEntityID, MacroDefinition *MD) { } + /// \brief A macro definition that had previously been deserialized + /// (and removed via IdentifierRead) has now been made visible. + virtual void MacroVisible(IdentifierInfo *II) { } + /// \brief A module definition was read from the AST file. + virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) { } }; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h index 996a134..9baaf4b 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h @@ -34,6 +34,8 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/DenseSet.h" @@ -162,16 +164,16 @@ private: void Error(const char *Msg); }; -namespace serialization { +namespace serialization { class ReadMethodPoolVisitor; - + namespace reader { class ASTIdentifierLookupTrait; } - + } // end namespace serialization - + /// \brief Reads an AST files chain containing the contents of a translation /// unit. /// @@ -191,7 +193,7 @@ class ASTReader public ExternalSemaSource, public IdentifierInfoLookup, public ExternalIdentifierLookup, - public ExternalSLocEntrySource + public ExternalSLocEntrySource { public: enum ASTReadResult { Success, Failure, IgnorePCH }; @@ -205,18 +207,18 @@ public: friend class ASTWriter; friend class ASTUnit; // ASTUnit needs to remap source locations. friend class serialization::ReadMethodPoolVisitor; - - typedef serialization::Module Module; + + typedef serialization::ModuleFile ModuleFile; typedef serialization::ModuleKind ModuleKind; typedef serialization::ModuleManager ModuleManager; - + typedef ModuleManager::ModuleIterator ModuleIterator; typedef ModuleManager::ModuleConstIterator ModuleConstIterator; typedef ModuleManager::ModuleReverseIterator ModuleReverseIterator; private: /// \brief The receiver of some callbacks invoked by ASTReader. - llvm::OwningPtr<ASTReaderListener> Listener; + OwningPtr<ASTReaderListener> Listener; /// \brief The receiver of deserialization events. ASTDeserializationListener *DeserializationListener; @@ -224,7 +226,7 @@ private: SourceManager &SourceMgr; FileManager &FileMgr; DiagnosticsEngine &Diags; - + /// \brief The semantic analysis object that will be processing the /// AST files and the translation unit that uses it. Sema *SemaObj; @@ -234,7 +236,7 @@ private: /// \brief The AST context into which we'll read the AST files. ASTContext &Context; - + /// \brief The AST consumer. ASTConsumer *Consumer; @@ -243,24 +245,24 @@ private: /// \brief A map of global bit offsets to the module that stores entities /// at those bit offsets. - ContinuousRangeMap<uint64_t, Module*, 4> GlobalBitOffsetsMap; + ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap; /// \brief A map of negated SLocEntryIDs to the modules containing them. - ContinuousRangeMap<unsigned, Module*, 64> GlobalSLocEntryMap; + ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap; + + typedef ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocOffsetMapType; - typedef ContinuousRangeMap<unsigned, Module*, 64> GlobalSLocOffsetMapType; - /// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset) /// SourceLocation offsets to the modules containing them. GlobalSLocOffsetMapType GlobalSLocOffsetMap; - + /// \brief Types that have already been loaded from the chain. /// /// When the pointer at index I is non-NULL, the type with /// ID = (I + 1) << FastQual::Width has already been loaded std::vector<QualType> TypesLoaded; - typedef ContinuousRangeMap<serialization::TypeID, Module *, 4> + typedef ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4> GlobalTypeMapType; /// \brief Mapping from global type IDs to the module in which the @@ -274,60 +276,67 @@ private: /// = I + 1 has already been loaded. std::vector<Decl *> DeclsLoaded; - typedef ContinuousRangeMap<serialization::DeclID, Module *, 4> + typedef ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4> GlobalDeclMapType; - + /// \brief Mapping from global declaration IDs to the module in which the /// declaration resides. GlobalDeclMapType GlobalDeclMap; - - typedef std::pair<Module *, uint64_t> FileOffset; + + typedef std::pair<ModuleFile *, uint64_t> FileOffset; typedef SmallVector<FileOffset, 2> FileOffsetsTy; typedef llvm::DenseMap<serialization::DeclID, FileOffsetsTy> DeclUpdateOffsetsMap; - + /// \brief Declarations that have modifications residing in a later file /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; - typedef llvm::DenseMap<serialization::DeclID, - std::pair<Module *, uint64_t> > + struct ReplacedDeclInfo { + ModuleFile *Mod; + uint64_t Offset; + unsigned RawLoc; + + ReplacedDeclInfo() : Mod(0), Offset(0), RawLoc(0) {} + ReplacedDeclInfo(ModuleFile *Mod, uint64_t Offset, unsigned RawLoc) + : Mod(Mod), Offset(Offset), RawLoc(RawLoc) {} + }; + + typedef llvm::DenseMap<serialization::DeclID, ReplacedDeclInfo> DeclReplacementMap; /// \brief Declarations that have been replaced in a later file in the chain. DeclReplacementMap ReplacedDecls; + struct FileDeclsInfo { + ModuleFile *Mod; + ArrayRef<serialization::LocalDeclID> Decls; + + FileDeclsInfo() : Mod(0) {} + FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls) + : Mod(Mod), Decls(Decls) {} + }; + + /// \brief Map from a FileID to the file-level declarations that it contains. + llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs; + // Updates for visible decls can occur for other contexts than just the // TU, and when we read those update records, the actual context will not // be available yet (unless it's the TU), so have this pending map using the // ID as a key. It will be realized when the context is actually loaded. - typedef SmallVector<std::pair<void *, Module*>, 1> DeclContextVisibleUpdates; + typedef SmallVector<std::pair<void *, ModuleFile*>, 1> DeclContextVisibleUpdates; typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates> DeclContextVisibleUpdatesPending; /// \brief Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. DeclContextVisibleUpdatesPending PendingVisibleUpdates; - - typedef SmallVector<CXXRecordDecl *, 4> ForwardRefs; - typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs> - PendingForwardRefsMap; - /// \brief Forward references that have a definition but the definition decl - /// is still initializing. When the definition gets read it will update - /// the DefinitionData pointer of all pending references. - PendingForwardRefsMap PendingForwardRefs; - - typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID> - FirstLatestDeclIDMap; - /// \brief Map of first declarations from a chained PCH that point to the - /// most recent declarations in another AST file. - FirstLatestDeclIDMap FirstLatestDeclIDs; - - /// \brief Set of ObjC interfaces that have categories chained to them in - /// other modules. - llvm::DenseSet<serialization::GlobalDeclID> ObjCChainedCategoriesInterfaces; - + + /// \brief The set of C++ or Objective-C classes that have forward + /// declarations that have not yet been linked to their definitions. + llvm::SmallPtrSet<Decl *, 4> PendingDefinitions; + /// \brief Read the records that describe the contents of declcontexts. - bool ReadDeclContextStorage(Module &M, + bool ReadDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, const std::pair<uint64_t, uint64_t> &Offsets, serialization::DeclContextInfo &Info); @@ -340,14 +349,62 @@ private: /// been loaded. std::vector<IdentifierInfo *> IdentifiersLoaded; - typedef ContinuousRangeMap<serialization::IdentID, Module *, 4> + typedef ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4> GlobalIdentifierMapType; - + /// \brief Mapping from global identifer IDs to the module in which the /// identifier resides along with the offset that should be added to the /// global identifier ID to produce a local ID. GlobalIdentifierMapType GlobalIdentifierMap; + /// \brief A vector containing submodules that have already been loaded. + /// + /// This vector is indexed by the Submodule ID (-1). NULL submodule entries + /// indicate that the particular submodule ID has not yet been loaded. + SmallVector<Module *, 2> SubmodulesLoaded; + + typedef ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4> + GlobalSubmoduleMapType; + + /// \brief Mapping from global submodule IDs to the module file in which the + /// submodule resides along with the offset that should be added to the + /// global submodule ID to produce a local ID. + GlobalSubmoduleMapType GlobalSubmoduleMap; + + /// \brief A set of hidden declarations. + typedef llvm::SmallVector<llvm::PointerUnion<Decl *, IdentifierInfo *>, 2> + HiddenNames; + + typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType; + + /// \brief A mapping from each of the hidden submodules to the deserialized + /// declarations in that submodule that could be made visible. + HiddenNamesMapType HiddenNamesMap; + + + /// \brief A module import or export that hasn't yet been resolved. + struct UnresolvedModuleImportExport { + /// \brief The file in which this module resides. + ModuleFile *File; + + /// \brief The module that is importing or exporting. + Module *Mod; + + /// \brief The local ID of the module that is being exported. + unsigned ID; + + /// \brief Whether this is an import (vs. an export). + unsigned IsImport : 1; + + /// \brief Whether this is a wildcard export. + unsigned IsWildcard : 1; + }; + + /// \brief The set of module imports and exports that still need to be + /// resolved. + llvm::SmallVector<UnresolvedModuleImportExport, 2> + UnresolvedModuleImportExports; + /// \brief A vector containing selectors that have already been loaded. /// /// This vector is indexed by the Selector ID (-1). NULL selector @@ -355,27 +412,31 @@ private: /// been loaded. SmallVector<Selector, 16> SelectorsLoaded; - typedef ContinuousRangeMap<serialization::SelectorID, Module *, 4> + typedef ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4> GlobalSelectorMapType; - + /// \brief Mapping from global selector IDs to the module in which the /// selector resides along with the offset that should be added to the /// global selector ID to produce a local ID. GlobalSelectorMapType GlobalSelectorMap; + /// \brief The generation number of the last time we loaded data from the + /// global method pool for this selector. + llvm::DenseMap<Selector, unsigned> SelectorGeneration; + /// \brief Mapping from identifiers that represent macros whose definitions /// have not yet been deserialized to the global offset where the macro /// record resides. llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets; - typedef ContinuousRangeMap<unsigned, Module *, 4> + typedef ContinuousRangeMap<unsigned, ModuleFile *, 4> GlobalPreprocessedEntityMapType; - + /// \brief Mapping from global preprocessing entity IDs to the module in /// which the preprocessed entity resides along with the offset that should be /// added to the global preprocessing entitiy ID to produce a local ID. GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap; - + /// \name CodeGen-relevant special data /// \brief Fields containing data that is relevant to CodeGen. //@{ @@ -423,7 +484,7 @@ private: /// \brief A list of all the delegating constructors we've seen, to diagnose /// cycles. SmallVector<uint64_t, 4> DelegatingCtorDecls; - + /// \brief Method selectors used in a @selector expression. Used for /// implementation of -Wselector. SmallVector<uint64_t, 64> ReferencedSelectorsData; @@ -480,6 +541,9 @@ private: /// \brief A list of the namespaces we've seen. SmallVector<uint64_t, 4> KnownNamespaces; + /// \brief A list of modules that were imported by precompiled headers or + /// any other non-module AST file. + SmallVector<serialization::SubmoduleID, 2> ImportedModules; //@} /// \brief The original file name that was used to build the primary AST file, @@ -493,7 +557,7 @@ private: /// \brief The file ID for the original file that was used to build the /// primary AST file. FileID OriginalFileID; - + /// \brief The directory that the PCH was originally created in. Used to /// allow resolving headers even after headers+PCH was moved to a new path. std::string OriginalDir; @@ -511,19 +575,23 @@ private: /// \brief Whether to disable the normal validation performed on precompiled /// headers when they are loaded. bool DisableValidation; - + /// \brief Whether to disable the use of stat caches in AST files. bool DisableStatCache; + /// \brief Whether to accept an AST file with compiler errors. + bool AllowASTWithCompilerErrors; + + /// \brief The current "generation" of the module file import stack, which + /// indicates how many separate module file load operations have occurred. + unsigned CurrentGeneration; + /// \brief Mapping from switch-case IDs in the chain to switch-case statements /// /// Statements usually don't have IDs, but switch cases need them, so that the /// switch statement can refer to them. std::map<unsigned, SwitchCase *> SwitchCaseStmts; - /// \brief Mapping from opaque value IDs to OpaqueValueExprs. - std::map<unsigned, OpaqueValueExpr*> OpaqueValueExprs; - /// \brief The number of stat() calls that hit/missed the stat /// cache. unsigned NumStatHits, NumStatMisses; @@ -567,13 +635,19 @@ private: /// Number of visible decl contexts read/total. unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts; - + /// Total size of modules, in bits, currently loaded uint64_t TotalModulesSizeInBits; /// \brief Number of Decl/types that are currently deserializing. unsigned NumCurrentElementsDeserializing; + /// \brief Set true while we are in the process of passing deserialized + /// "interesting" decls to consumer inside FinishedDeserializing(). + /// This is used as a guard to avoid recursively repeating the process of + /// passing decls to consumer. + bool PassingDeclsToConsumer; + /// Number of CXX base specifiers currently loaded unsigned NumCXXBaseSpecifiersLoaded; @@ -591,6 +665,10 @@ private: /// loaded once the recursive loading has completed. std::deque<PendingIdentifierInfo> PendingIdentifierInfos; + /// \brief The generation number of each identifier, which keeps track of + /// the last time we loaded information about this identifier. + llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration; + /// \brief Contains declarations and definitions that will be /// "interesting" to the ASTConsumer, when we get that AST consumer. /// @@ -599,10 +677,58 @@ private: /// Objective-C protocols. std::deque<Decl *> InterestingDecls; - /// \brief We delay loading of the previous declaration chain to avoid - /// deeply nested calls when there are many redeclarations. - std::deque<std::pair<Decl *, serialization::DeclID> > PendingPreviousDecls; - + /// \brief The set of redeclarable declaraations that have been deserialized + /// since the last time the declaration chains were linked. + llvm::SmallPtrSet<Decl *, 16> RedeclsDeserialized; + + /// \brief The list of redeclaration chains that still need to be + /// reconstructed. + /// + /// Each element is the global declaration ID of the first declaration in + /// the chain. Elements in this vector should be unique; use + /// PendingDeclChainsKnown to ensure uniqueness. + llvm::SmallVector<serialization::DeclID, 16> PendingDeclChains; + + /// \brief Keeps track of the elements added to PendingDeclChains. + llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown; + + /// \brief The set of Objective-C categories that have been deserialized + /// since the last time the declaration chains were linked. + llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized; + + /// \brief The set of Objective-C class definitions that have already been + /// loaded, for which we will need to check for categories whenever a new + /// module is loaded. + llvm::SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; + + typedef llvm::DenseMap<Decl *, llvm::SmallVector<serialization::DeclID, 2> > + MergedDeclsMap; + + /// \brief A mapping from canonical declarations to the set of additional + /// (global, previously-canonical) declaration IDs that have been merged with + /// that canonical declaration. + MergedDeclsMap MergedDecls; + + typedef llvm::DenseMap<serialization::GlobalDeclID, + llvm::SmallVector<serialization::DeclID, 2> > + StoredMergedDeclsMap; + + /// \brief A mapping from canonical declaration IDs to the set of additional + /// declaration IDs that have been merged with that canonical declaration. + /// + /// This is the deserialized representation of the entries in MergedDecls. + /// When we query entries in MergedDecls, they will be augmented with entries + /// from StoredMergedDecls. + StoredMergedDeclsMap StoredMergedDecls; + + /// \brief Combine the stored merged declarations for the given canonical + /// declaration into the set of merged declarations. + /// + /// \returns An iterator into MergedDecls that corresponds to the position of + /// the given canonical declaration. + MergedDeclsMap::iterator + combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID); + /// \brief Ready to load the previous declaration of the given Decl. void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID); @@ -614,7 +740,7 @@ private: Read_Decl, Read_Type, Read_Stmt }; - /// \brief What kind of records we are reading. + /// \brief What kind of records we are reading. ReadingKind ReadingKind; /// \brief RAII object to change the reading kind. @@ -649,7 +775,7 @@ private: std::string SuggestedPredefines; /// \brief Reads a statement from the specified cursor. - Stmt *ReadStmtFromStream(Module &F); + Stmt *ReadStmtFromStream(ModuleFile &F); /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take /// into account all the necessary relocations. @@ -658,20 +784,21 @@ private: void MaybeAddSystemRootToFilename(std::string &Filename); ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type, - Module *ImportedBy); - ASTReadResult ReadASTBlock(Module &F); + ModuleFile *ImportedBy); + ASTReadResult ReadASTBlock(ModuleFile &F); bool CheckPredefinesBuffers(); - bool ParseLineTable(Module &F, SmallVectorImpl<uint64_t> &Record); - ASTReadResult ReadSourceManagerBlock(Module &F); + bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); + ASTReadResult ReadSourceManagerBlock(ModuleFile &F); ASTReadResult ReadSLocEntryRecord(int ID); llvm::BitstreamCursor &SLocCursorForID(int ID); - SourceLocation getImportLocation(Module *F); + SourceLocation getImportLocation(ModuleFile *F); + ASTReadResult ReadSubmoduleBlock(ModuleFile &F); bool ParseLanguageOptions(const SmallVectorImpl<uint64_t> &Record); - + struct RecordLocation { - RecordLocation(Module *M, uint64_t O) + RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {} - Module *F; + ModuleFile *F; uint64_t Offset; }; @@ -679,19 +806,22 @@ private: RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); Decl *ReadDeclRecord(serialization::DeclID ID); - RecordLocation DeclCursorForID(serialization::DeclID ID); + RecordLocation DeclCursorForID(serialization::DeclID ID, + unsigned &RawLocation); void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); - void loadObjCChainedCategories(serialization::GlobalDeclID ID, - ObjCInterfaceDecl *D); - + void loadPendingDeclChain(serialization::GlobalDeclID ID); + void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D, + unsigned PreviousGeneration = 0); + RecordLocation getLocalBitOffset(uint64_t GlobalOffset); - uint64_t getGlobalBitOffset(Module &M, uint32_t LocalOffset); + uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset); /// \brief Returns the first preprocessed entity ID that ends after \arg BLoc. serialization::PreprocessedEntityID findBeginPreprocessedEntity(SourceLocation BLoc) const; - /// \brief Returns the first preprocessed entity ID that begins after \arg ELoc. + /// \brief Returns the first preprocessed entity ID that begins after \arg + /// ELoc. serialization::PreprocessedEntityID findEndPreprocessedEntity(SourceLocation ELoc) const; @@ -703,7 +833,15 @@ private: findNextPreprocessedEntity( GlobalSLocOffsetMapType::const_iterator SLocMapI) const; + /// \brief Returns (ModuleFile, Local index) pair for \arg GlobalIndex of a + /// preprocessed entity. + std::pair<ModuleFile *, unsigned> + getModulePreprocessedEntity(unsigned GlobalIndex); + void PassInterestingDeclsToConsumer(); + void PassInterestingDeclToConsumer(Decl *D); + + void finishPendingActions(); /// \brief Produce an error diagnostic and return true. /// @@ -740,20 +878,38 @@ public: /// help when an AST file is being used in cases where the /// underlying files in the file system may have changed, but /// parsing should still continue. + /// + /// \param AllowASTWithCompilerErrors If true, the AST reader will accept an + /// AST file the was created out of an AST with compiler errors, + /// otherwise it will reject it. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", - bool DisableValidation = false, bool DisableStatCache = false); + bool DisableValidation = false, bool DisableStatCache = false, + bool AllowASTWithCompilerErrors = false); ~ASTReader(); SourceManager &getSourceManager() const { return SourceMgr; } - + /// \brief Load the AST file designated by the given file name. ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type); /// \brief Checks that no file that is stored in PCH is out-of-sync with /// the actual file in the file system. - ASTReadResult validateFileEntries(Module &M); + ASTReadResult validateFileEntries(ModuleFile &M); + /// \brief Make the entities in the given module and any of its (non-explicit) + /// submodules visible to name lookup. + /// + /// \param Mod The module whose names should be made visible. + /// + /// \param Visibility The level of visibility to give the names in the module. + /// Visibility can only be increased over time. + void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind NameVisibility); + + /// \brief Make the names within this set of hidden names visible. + void makeNamesVisible(const HiddenNames &Names); + /// \brief Set the AST callbacks listener. void setListener(ASTReaderListener *listener) { Listener.reset(listener); @@ -770,12 +926,19 @@ public: ModuleMgr.addInMemoryBuffer(FileName, Buffer); } + /// \brief Finalizes the AST reader's state before writing an AST file to + /// disk. + /// + /// This operation may undo temporary state in the AST that should not be + /// emitted. + void finalizeForWriting(); + /// \brief Retrieve the module manager. ModuleManager &getModuleManager() { return ModuleMgr; } /// \brief Retrieve the preprocessor. Preprocessor &getPreprocessor() const { return PP; } - + /// \brief Retrieve the name of the original source file name const std::string &getOriginalSourceFile() { return OriginalFileName; } @@ -801,6 +964,11 @@ public: virtual std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range); + /// \brief Optionally returns true or false if the preallocated preprocessed + /// entity with index \arg Index came from file \arg FID. + virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID); + /// \brief Read the header file information for the given file entry. virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE); @@ -826,6 +994,11 @@ public: return static_cast<unsigned>(DeclsLoaded.size()); } + /// \brief Returns the number of submodules known. + unsigned getTotalNumSubmodules() const { + return static_cast<unsigned>(SubmodulesLoaded.size()); + } + /// \brief Returns the number of selectors found in the chain. unsigned getTotalNumSelectors() const { return static_cast<unsigned>(SelectorsLoaded.size()); @@ -839,28 +1012,28 @@ public: E = ModuleMgr.end(); I != E; ++I) { Result += (*I)->NumPreprocessedEntities; } - + return Result; } - + /// \brief Returns the number of C++ base specifiers found in the chain. unsigned getTotalNumCXXBaseSpecifiers() const { return NumCXXBaseSpecifiersLoaded; } - + /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo - GetTemplateArgumentLocInfo(Module &F, TemplateArgument::ArgKind Kind, + GetTemplateArgumentLocInfo(ModuleFile &F, TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Idx); /// \brief Reads a TemplateArgumentLoc. TemplateArgumentLoc - ReadTemplateArgumentLoc(Module &F, + ReadTemplateArgumentLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Reads a declarator info from the given record. - TypeSourceInfo *GetTypeSourceInfo(Module &F, + TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Resolve a type ID into a type, potentially building a new @@ -868,35 +1041,42 @@ public: QualType GetType(serialization::TypeID ID); /// \brief Resolve a local type ID within a given AST file into a type. - QualType getLocalType(Module &F, unsigned LocalID); - + QualType getLocalType(ModuleFile &F, unsigned LocalID); + /// \brief Map a local type ID within a given AST file into a global type ID. - serialization::TypeID getGlobalTypeID(Module &F, unsigned LocalID) const; - - /// \brief Read a type from the current position in the given record, which + serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const; + + /// \brief Read a type from the current position in the given record, which /// was read from the given AST file. - QualType readType(Module &F, const RecordData &Record, unsigned &Idx) { + QualType readType(ModuleFile &F, const RecordData &Record, unsigned &Idx) { if (Idx >= Record.size()) return QualType(); - + return getLocalType(F, Record[Idx++]); } - - /// \brief Map from a local declaration ID within a given module to a + + /// \brief Map from a local declaration ID within a given module to a /// global declaration ID. - serialization::DeclID getGlobalDeclID(Module &F, unsigned LocalID) const; + serialization::DeclID getGlobalDeclID(ModuleFile &F, unsigned LocalID) const; /// \brief Returns true if global DeclID \arg ID originated from module /// \arg M. - bool isDeclIDFromModule(serialization::GlobalDeclID ID, Module &M) const; + bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const; + + /// \brief Retrieve the module file that owns the given declaration, or NULL + /// if the declaration is not from a module file. + ModuleFile *getOwningModuleFile(Decl *D); + /// \brief Returns the source location for the decl \arg ID. + SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); + /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. Decl *GetDecl(serialization::DeclID ID); virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Reads a declaration with the given local ID in the given module. - Decl *GetLocalDecl(Module &F, uint32_t LocalID) { + Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) { return GetDecl(getGlobalDeclID(F, LocalID)); } @@ -904,40 +1084,49 @@ public: /// /// \returns The requested declaration, casted to the given return type. template<typename T> - T *GetLocalDeclAs(Module &F, uint32_t LocalID) { + T *GetLocalDeclAs(ModuleFile &F, uint32_t LocalID) { return cast_or_null<T>(GetLocalDecl(F, LocalID)); } - /// \brief Reads a declaration ID from the given position in a record in the + /// \brief Map a global declaration ID into the declaration ID used to + /// refer to this declaration within the given module fule. + /// + /// \returns the global ID of the given declaration as known in the given + /// module file. + serialization::DeclID + mapGlobalIDToModuleFileGlobalID(ModuleFile &M, + serialization::DeclID GlobalID); + + /// \brief Reads a declaration ID from the given position in a record in the /// given module. /// /// \returns The declaration ID read from the record, adjusted to a global ID. - serialization::DeclID ReadDeclID(Module &F, const RecordData &Record, + serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx); - + /// \brief Reads a declaration from the given position in a record in the /// given module. - Decl *ReadDecl(Module &F, const RecordData &R, unsigned &I) { + Decl *ReadDecl(ModuleFile &F, const RecordData &R, unsigned &I) { return GetDecl(ReadDeclID(F, R, I)); } - + /// \brief Reads a declaration from the given position in a record in the /// given module. /// /// \returns The declaration read from this location, casted to the given /// result type. template<typename T> - T *ReadDeclAs(Module &F, const RecordData &R, unsigned &I) { + T *ReadDeclAs(ModuleFile &F, const RecordData &R, unsigned &I) { return cast_or_null<T>(GetDecl(ReadDeclID(F, R, I))); } /// \brief Read a CXXBaseSpecifiers ID form the given record and /// return its global bit offset. - uint64_t readCXXBaseSpecifiers(Module &M, const RecordData &Record, + uint64_t readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, unsigned &Idx); - + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - + /// \brief Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external @@ -974,6 +1163,12 @@ public: bool (*isKindWeWant)(Decl::Kind), SmallVectorImpl<Decl*> &Decls); + /// \brief Get the decls that are contained in a file in the Offset/Length + /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// a range. + virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, + SmallVectorImpl<Decl *> &Decls); + /// \brief Notify ASTReader that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. @@ -995,7 +1190,7 @@ public: /// \brief Dump information about the AST reader to standard error. void dump(); - + /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; @@ -1025,11 +1220,7 @@ public: /// \brief Load the contents of the global method pool for a given /// selector. - /// - /// \returns a pair of Objective-C methods lists containing the - /// instance and factory methods, respectively, with this selector. - virtual std::pair<ObjCMethodList, ObjCMethodList> - ReadMethodPool(Selector Sel); + virtual void ReadMethodPool(Selector Sel); /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. @@ -1051,7 +1242,7 @@ public: virtual void ReadLocallyScopedExternalDecls( SmallVectorImpl<NamedDecl *> &Decls); - + virtual void ReadReferencedSelectors( SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels); @@ -1061,7 +1252,7 @@ public: virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables); virtual void ReadPendingInstantiations( - SmallVectorImpl<std::pair<ValueDecl *, + SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending); /// \brief Load a selector from disk, registering its ID if it exists. @@ -1080,7 +1271,7 @@ public: IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID); - IdentifierInfo *GetIdentifierInfo(Module &M, const RecordData &Record, + IdentifierInfo *GetIdentifierInfo(ModuleFile &M, const RecordData &Record, unsigned &Idx) { return DecodeIdentifierInfo(getGlobalIdentifierID(M, Record[Idx++])); } @@ -1089,101 +1280,110 @@ public: return DecodeIdentifierInfo(ID); } - IdentifierInfo *getLocalIdentifier(Module &M, unsigned LocalID); - - serialization::IdentifierID getGlobalIdentifierID(Module &M, + IdentifierInfo *getLocalIdentifier(ModuleFile &M, unsigned LocalID); + + serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); - + /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); + /// \brief Retrieve the global submodule ID given a module and its local ID + /// number. + serialization::SubmoduleID + getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID); + + /// \brief Retrieve the submodule that corresponds to a global submodule ID. + /// + Module *getSubmodule(serialization::SubmoduleID GlobalID); + /// \brief Retrieve a selector from the given module with its local ID /// number. - Selector getLocalSelector(Module &M, unsigned LocalID); + Selector getLocalSelector(ModuleFile &M, unsigned LocalID); Selector DecodeSelector(serialization::SelectorID Idx); virtual Selector GetExternalSelector(serialization::SelectorID ID); uint32_t GetNumExternalSelectors(); - Selector ReadSelector(Module &M, const RecordData &Record, unsigned &Idx) { + Selector ReadSelector(ModuleFile &M, const RecordData &Record, unsigned &Idx) { return getLocalSelector(M, Record[Idx++]); } - + /// \brief Retrieve the global selector ID that corresponds to this /// the local selector ID in a given module. - serialization::SelectorID getGlobalSelectorID(Module &F, + serialization::SelectorID getGlobalSelectorID(ModuleFile &F, unsigned LocalID) const; /// \brief Read a declaration name. - DeclarationName ReadDeclarationName(Module &F, + DeclarationName ReadDeclarationName(ModuleFile &F, const RecordData &Record, unsigned &Idx); - void ReadDeclarationNameLoc(Module &F, + void ReadDeclarationNameLoc(ModuleFile &F, DeclarationNameLoc &DNLoc, DeclarationName Name, const RecordData &Record, unsigned &Idx); - void ReadDeclarationNameInfo(Module &F, DeclarationNameInfo &NameInfo, + void ReadDeclarationNameInfo(ModuleFile &F, DeclarationNameInfo &NameInfo, const RecordData &Record, unsigned &Idx); - void ReadQualifierInfo(Module &F, QualifierInfo &Info, + void ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info, const RecordData &Record, unsigned &Idx); - NestedNameSpecifier *ReadNestedNameSpecifier(Module &F, + NestedNameSpecifier *ReadNestedNameSpecifier(ModuleFile &F, const RecordData &Record, unsigned &Idx); - NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(Module &F, + NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Read a template name. - TemplateName ReadTemplateName(Module &F, const RecordData &Record, + TemplateName ReadTemplateName(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Read a template argument. - TemplateArgument ReadTemplateArgument(Module &F, + TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,unsigned &Idx); - + /// \brief Read a template parameter list. - TemplateParameterList *ReadTemplateParameterList(Module &F, + TemplateParameterList *ReadTemplateParameterList(ModuleFile &F, const RecordData &Record, unsigned &Idx); - + /// \brief Read a template argument array. void ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, - Module &F, const RecordData &Record, + ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Read a UnresolvedSet structure. - void ReadUnresolvedSet(Module &F, UnresolvedSetImpl &Set, + void ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, const RecordData &Record, unsigned &Idx); /// \brief Read a C++ base specifier. - CXXBaseSpecifier ReadCXXBaseSpecifier(Module &F, + CXXBaseSpecifier ReadCXXBaseSpecifier(ModuleFile &F, const RecordData &Record,unsigned &Idx); /// \brief Read a CXXCtorInitializer array. std::pair<CXXCtorInitializer **, unsigned> - ReadCXXCtorInitializers(Module &F, const RecordData &Record, + ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx); /// \brief Read a source location from raw form. - SourceLocation ReadSourceLocation(Module &Module, unsigned Raw) const { + SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, unsigned Raw) const { SourceLocation Loc = SourceLocation::getFromRawEncoding(Raw); - assert(Module.SLocRemap.find(Loc.getOffset()) != Module.SLocRemap.end() && + assert(ModuleFile.SLocRemap.find(Loc.getOffset()) != ModuleFile.SLocRemap.end() && "Cannot find offset to remap."); - int Remap = Module.SLocRemap.find(Loc.getOffset())->second; + int Remap = ModuleFile.SLocRemap.find(Loc.getOffset())->second; return Loc.getLocWithOffset(Remap); } /// \brief Read a source location. - SourceLocation ReadSourceLocation(Module &Module, + SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, const RecordData &Record, unsigned& Idx) { - return ReadSourceLocation(Module, Record[Idx++]); + return ReadSourceLocation(ModuleFile, Record[Idx++]); } /// \brief Read a source range. - SourceRange ReadSourceRange(Module &F, + SourceRange ReadSourceRange(ModuleFile &F, const RecordData &Record, unsigned& Idx); /// \brief Read an integral value @@ -1201,18 +1401,18 @@ public: /// \brief Read a version tuple. VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); - CXXTemporary *ReadCXXTemporary(Module &F, const RecordData &Record, + CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx); - + /// \brief Reads attributes from the current stream position. - void ReadAttributes(Module &F, AttrVec &Attrs, + void ReadAttributes(ModuleFile &F, AttrVec &Attrs, const RecordData &Record, unsigned &Idx); /// \brief Reads a statement. - Stmt *ReadStmt(Module &F); + Stmt *ReadStmt(ModuleFile &F); /// \brief Reads an expression. - Expr *ReadExpr(Module &F); + Expr *ReadExpr(ModuleFile &F); /// \brief Reads a sub-statement operand during statement reading. Stmt *ReadSubStmt() { @@ -1228,29 +1428,47 @@ public: Expr *ReadSubExpr(); /// \brief Reads the macro record located at the given offset. - void ReadMacroRecord(Module &F, uint64_t Offset); - + void ReadMacroRecord(ModuleFile &F, uint64_t Offset); + /// \brief Determine the global preprocessed entity ID that corresponds to /// the given local ID within the given module. - serialization::PreprocessedEntityID - getGlobalPreprocessedEntityID(Module &M, unsigned LocalID) const; - + serialization::PreprocessedEntityID + getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const; + /// \brief Note that the identifier is a macro whose record will be loaded /// from the given AST file at the given (file-local) offset. - void SetIdentifierIsMacro(IdentifierInfo *II, Module &F, - uint64_t Offset); - + /// + /// \param II The name of the macro. + /// + /// \param F The module file from which the macro definition was deserialized. + /// + /// \param Offset The offset into the module file at which the macro + /// definition is located. + /// + /// \param Visible Whether the macro should be made visible. + void setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, + uint64_t Offset, bool Visible); + /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); /// \brief Read the macro definition for this identifier. virtual void LoadMacroDefinition(IdentifierInfo *II); + /// \brief Update an out-of-date identifier. + virtual void updateOutOfDateIdentifier(IdentifierInfo &II); + + /// \brief Note that this identifier is up-to-date. + void markIdentifierUpToDate(IdentifierInfo *II); + /// \brief Read the macro definition corresponding to this iterator /// into the unread macro record offsets table. void LoadMacroDefinition( llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos); - + + /// \brief Load all external visible decls in the given DeclContext. + void completeVisibleDeclsMap(DeclContext *DC); + /// \brief Retrieve the AST context that this AST reader supplements. ASTContext &getContext() { return Context; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h index 7a49e48..4c62385 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h @@ -24,6 +24,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamWriter.h" #include <map> #include <queue> @@ -43,11 +45,13 @@ class CXXBaseSpecifier; class CXXCtorInitializer; class FPOptions; class HeaderSearch; +class IdentifierResolver; class MacroDefinition; class MemorizeStatCalls; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; +class Module; class PreprocessedEntity; class PreprocessingRecord; class Preprocessor; @@ -57,6 +61,8 @@ class SwitchCase; class TargetInfo; class VersionTuple; +namespace SrcMgr { class SLocEntry; } + /// \brief Writes an AST file containing the contents of a translation unit. /// /// The ASTWriter class produces a bitstream containing the serialized @@ -80,7 +86,7 @@ private: /// allow for the const/volatile qualifiers. /// /// Keys in the map never have const/volatile qualifiers. - typedef llvm::DenseMap<QualType, serialization::TypeIdx, + typedef llvm::DenseMap<QualType, serialization::TypeIdx, serialization::UnsafeQualTypeDenseMapInfo> TypeIdxMap; @@ -89,33 +95,42 @@ private: /// \brief The ASTContext we're writing. ASTContext *Context; - + + /// \brief The preprocessor we're writing. + Preprocessor *PP; + /// \brief The reader of existing AST files, if we're chaining. ASTReader *Chain; - - /// \brief Indicates when the AST writing is actively performing + + /// \brief The module we're currently writing, if any. + Module *WritingModule; + + /// \brief Indicates when the AST writing is actively performing /// serialization, rather than just queueing updates. bool WritingAST; - + + /// \brief Indicates that the AST contained compiler errors. + bool ASTHasCompilerErrors; + /// \brief Stores a declaration or a type to be written to the AST file. class DeclOrType { public: DeclOrType(Decl *D) : Stored(D), IsType(false) { } DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { } - + bool isType() const { return IsType; } bool isDecl() const { return !IsType; } - + QualType getType() const { assert(isType() && "Not a type!"); return QualType::getFromOpaquePtr(Stored); } - + Decl *getDecl() const { assert(isDecl() && "Not a decl!"); return static_cast<Decl *>(Stored); } - + private: void *Stored; bool IsType; @@ -140,7 +155,25 @@ private: /// \brief Offset of each declaration in the bitstream, indexed by /// the declaration's ID. - std::vector<uint32_t> DeclOffsets; + std::vector<serialization::DeclOffset> DeclOffsets; + + /// \brief Sorted (by file offset) vector of pairs of file offset/DeclID. + typedef SmallVector<std::pair<unsigned, serialization::DeclID>, 64> + LocDeclIDsTy; + struct DeclIDInFileInfo { + LocDeclIDsTy DeclIDs; + /// \brief Set when the DeclIDs vectors from all files are joined, this + /// indicates the index that this particular vector has in the global one. + unsigned FirstDeclIndex; + }; + typedef llvm::DenseMap<const SrcMgr::SLocEntry *, + DeclIDInFileInfo *> FileDeclIDsTy; + + /// \brief Map from file SLocEntries to info about the file-level declarations + /// that it contains. + FileDeclIDsTy FileDeclIDs; + + void associateDeclWithFile(const Decl *D, serialization::DeclID); /// \brief The first ID number we can use for our own types. serialization::TypeID FirstTypeID; @@ -177,14 +210,32 @@ private: /// IdentifierInfo. llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs; + /// @name FlushStmt Caches + /// @{ + + /// \brief Set of parent Stmts for the currently serializing sub stmt. + llvm::DenseSet<Stmt *> ParentStmts; + + /// \brief Offsets of sub stmts already serialized. The offset points + /// just after the stmt record. + llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries; + + /// @} + /// \brief Offsets of each of the identifier IDs into the identifier /// table. std::vector<uint32_t> IdentifierOffsets; + /// \brief The first ID number we can use for our own submodules. + serialization::SubmoduleID FirstSubmoduleID; + + /// \brief The submodule ID that will be assigned to the next new submodule. + serialization::SubmoduleID NextSubmoduleID; + /// \brief The first ID number we can use for our own selectors. serialization::SelectorID FirstSelectorID; - /// \brief The selector ID that will be assigned to the next new identifier. + /// \brief The selector ID that will be assigned to the next new selector. serialization::SelectorID NextSelectorID; /// \brief Map that provides the ID numbers of each Selector. @@ -193,7 +244,7 @@ private: /// \brief Offset of each selector within the method pool/selector /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - + /// \brief Offsets of each of the macro identifiers into the /// bitstream. /// @@ -204,7 +255,7 @@ private: /// \brief The set of identifiers that had macro definitions at some point. std::vector<const IdentifierInfo *> DeserializedMacroNames; - + /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> @@ -220,7 +271,7 @@ private: /// \brief Map of first declarations from a chained PCH that point to the /// most recent declarations in another PCH. FirstLatestDeclMap FirstLatestDecls; - + /// \brief Declarations encountered that might be external /// definitions. /// @@ -238,31 +289,30 @@ private: /// \brief DeclContexts that have received extensions since their serialized /// form. /// - /// For namespaces, when we're chaining and encountering a namespace, we check if - /// its primary namespace comes from the chain. If it does, we add the primary - /// to this set, so that we can write out lexical content updates for it. + /// For namespaces, when we're chaining and encountering a namespace, we check + /// if its primary namespace comes from the chain. If it does, we add the + /// primary to this set, so that we can write out lexical content updates for + /// it. llvm::SmallPtrSet<const DeclContext *, 16> UpdatedDeclContexts; typedef llvm::SmallPtrSet<const Decl *, 16> DeclsToRewriteTy; /// \brief Decls that will be replaced in the current dependent AST file. DeclsToRewriteTy DeclsToRewrite; - struct ChainedObjCCategoriesData { - /// \brief The interface in the imported module. - const ObjCInterfaceDecl *Interface; - /// \brief The local tail category ID that got chained to the imported - /// interface. - const ObjCCategoryDecl *TailCategory; - - /// \brief ID corresponding to \c Interface. - serialization::DeclID InterfaceID; - - /// \brief ID corresponding to TailCategoryID. - serialization::DeclID TailCategoryID; + /// \brief The set of Objective-C class that have categories we + /// should serialize. + llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories; + + struct ReplacedDeclInfo { + serialization::DeclID ID; + uint64_t Offset; + unsigned Loc; + + ReplacedDeclInfo() : ID(0), Offset(0), Loc(0) {} + ReplacedDeclInfo(serialization::DeclID ID, uint64_t Offset, + SourceLocation Loc) + : ID(ID), Offset(Offset), Loc(Loc.getRawEncoding()) {} }; - /// \brief ObjC categories that got chained to an interface imported from - /// another module. - SmallVector<ChainedObjCCategoriesData, 16> LocalChainedObjCCategories; /// \brief Decls that have been replaced in the current dependent AST file. /// @@ -270,23 +320,24 @@ private: /// happen, but the ObjC AST nodes are designed this way), it will be /// serialized again. In this case, it is registered here, so that the reader /// knows to read the updated version. - SmallVector<std::pair<serialization::DeclID, uint64_t>, 16> - ReplacedDecls; - + SmallVector<ReplacedDeclInfo, 16> ReplacedDecls; + + /// \brief The set of declarations that may have redeclaration chains that + /// need to be serialized. + llvm::SetVector<Decl *, llvm::SmallVector<Decl *, 4>, + llvm::SmallPtrSet<Decl *, 4> > Redeclarations; + /// \brief Statements that we've encountered while serializing a /// declaration or type. SmallVector<Stmt *, 16> StmtsToEmit; /// \brief Statements collection to use for ASTWriter::AddStmt(). - /// It will point to StmtsToEmit unless it is overriden. + /// It will point to StmtsToEmit unless it is overriden. SmallVector<Stmt *, 16> *CollectedStmts; /// \brief Mapping from SwitchCase statements to IDs. std::map<SwitchCase *, unsigned> SwitchCaseIDs; - /// \brief Mapping from OpaqueValueExpr expressions to IDs. - llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues; - /// \brief The number of statements written to the AST file. unsigned NumStatements; @@ -303,35 +354,44 @@ private: /// \brief The offset of each CXXBaseSpecifier set within the AST. SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets; - + /// \brief The first ID number we can use for our own base specifiers. serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID; - - /// \brief The base specifiers ID that will be assigned to the next new + + /// \brief The base specifiers ID that will be assigned to the next new /// set of C++ base specifiers. serialization::CXXBaseSpecifiersID NextCXXBaseSpecifiersID; - /// \brief A set of C++ base specifiers that is queued to be written into the - /// AST file. + /// \brief A set of C++ base specifiers that is queued to be written into the + /// AST file. struct QueuedCXXBaseSpecifiers { QueuedCXXBaseSpecifiers() : ID(), Bases(), BasesEnd() { } - + QueuedCXXBaseSpecifiers(serialization::CXXBaseSpecifiersID ID, CXXBaseSpecifier const *Bases, CXXBaseSpecifier const *BasesEnd) : ID(ID), Bases(Bases), BasesEnd(BasesEnd) { } - + serialization::CXXBaseSpecifiersID ID; CXXBaseSpecifier const * Bases; CXXBaseSpecifier const * BasesEnd; }; - + /// \brief Queue of C++ base specifiers to be written to the AST file, /// in the order they should be written. SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite; + + /// \brief A mapping from each known submodule to its ID number, which will + /// be a positive integer. + llvm::DenseMap<Module *, unsigned> SubmoduleIDs; + + /// \brief Retrieve or create a submodule ID for this module. + unsigned getSubmoduleID(Module *Mod); /// \brief Write the given subexpression to the bitstream. - void WriteSubStmt(Stmt *S); + void WriteSubStmt(Stmt *S, + llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries, + llvm::DenseSet<Stmt *> &ParentStmts); void WriteBlockInfoBlock(); void WriteMetadata(ASTContext &Context, StringRef isysroot, @@ -342,27 +402,32 @@ private: const Preprocessor &PP, StringRef isysroot); void WritePreprocessor(const Preprocessor &PP, bool IsModule); - void WriteHeaderSearch(HeaderSearch &HS, StringRef isysroot); + void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot); void WritePreprocessorDetail(PreprocessingRecord &PPRec); + void WriteSubmodules(Module *WritingModule); + void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag); void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); void WriteTypeDeclOffsets(); + void WriteFileDeclIDsMap(); void WriteSelectors(Sema &SemaRef); void WriteReferencedSelectorsPool(Sema &SemaRef); - void WriteIdentifierTable(Preprocessor &PP, bool IsModule); + void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, + bool IsModule); void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); - void ResolveChainedObjCCategories(); - void WriteChainedObjCCategories(); void WriteDeclContextVisibleUpdate(const DeclContext *DC); void WriteFPPragmaOptions(const FPOptions &Opts); void WriteOpenCLExtensions(Sema &SemaRef); - + void WriteObjCCategories(); + void WriteRedeclarations(); + void WriteMergedDecls(); + unsigned DeclParmVarAbbrev; unsigned DeclContextLexicalAbbrev; unsigned DeclContextVisibleLookupAbbrev; @@ -382,13 +447,14 @@ private: void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, StringRef isysroot, const std::string &OutputFile, - bool IsModule); - + Module *WritingModule); + public: /// \brief Create a new precompiled header writer that outputs to /// the given bitstream. ASTWriter(llvm::BitstreamWriter &Stream); - + ~ASTWriter(); + /// \brief Write a precompiled header for the given semantic analysis. /// /// \param SemaRef a reference to the semantic analysis object that processed @@ -397,21 +463,22 @@ public: /// \param StatCalls the object that cached all of the stat() calls made while /// searching for source files and headers. /// - /// \param IsModule Whether we're writing a module (otherwise, we're writing a - /// precompiled header). + /// \param WritingModule The module that we are writing. If null, we are + /// writing a precompiled header. /// /// \param isysroot if non-empty, write a relocatable file whose headers /// are relative to the given system root. void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, const std::string &OutputFile, - bool IsModule, StringRef isysroot); + Module *WritingModule, StringRef isysroot, + bool hasErrors = false); /// \brief Emit a source location. void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record); /// \brief Emit a source range. void AddSourceRange(SourceRange Range, RecordDataImpl &Record); - + /// \brief Emit an integral value. void AddAPInt(const llvm::APInt &Value, RecordDataImpl &Record); @@ -434,10 +501,10 @@ public: void AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases, CXXBaseSpecifier const *BasesEnd, RecordDataImpl &Record); - + /// \brief Get the unique number used to refer to the given selector. serialization::SelectorID getSelectorRef(Selector Sel); - + /// \brief Get the unique number used to refer to the given identifier. serialization::IdentID getIdentifierRef(const IdentifierInfo *II); @@ -450,7 +517,7 @@ public: "Identifier does not name a macro"); return MacroOffsets[II]; } - + /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); @@ -484,7 +551,7 @@ public: /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); - + /// \brief Force a declaration to be emitted and get its ID. serialization::DeclID GetDeclRef(const Decl *D); @@ -505,9 +572,9 @@ public: void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record); /// \brief Emit a nested name specifier with source-location information. - void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, RecordDataImpl &Record); - + /// \brief Emit a template name. void AddTemplateName(TemplateName Name, RecordDataImpl &Record); @@ -526,7 +593,8 @@ public: void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record); /// \brief Emit a C++ base specifier. - void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordDataImpl &Record); + void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, + RecordDataImpl &Record); /// \brief Emit a CXXCtorInitializer array. void AddCXXCtorInitializers( @@ -549,10 +617,16 @@ public: void RewriteDecl(const Decl *D) { DeclsToRewrite.insert(D); - // Reset the flag, so that we don't add this decl multiple times. - const_cast<Decl *>(D)->setChangedSinceDeserialization(false); } + bool isRewritten(const Decl *D) const { + return DeclsToRewrite.count(D); + } + + /// \brief Infer the submodule ID that contains an entity at the given + /// source location. + serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); + /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); @@ -577,10 +651,10 @@ public: /// been added to the queue via AddStmt(). void FlushStmts(); - /// \brief Flush all of the C++ base specifier sets that have been added + /// \brief Flush all of the C++ base specifier sets that have been added /// via \c AddCXXBaseSpecifiersRef(). void FlushCXXBaseSpecifiers(); - + /// \brief Record an ID for the given switch-case statement. unsigned RecordSwitchCaseID(SwitchCase *S); @@ -589,9 +663,6 @@ public: void ClearSwitchCaseIDs(); - /// \brief Retrieve the ID for the given opaque value expression. - unsigned getOpaqueValueID(OpaqueValueExpr *e); - unsigned getDeclParmVarAbbrev() const { return DeclParmVarAbbrev; } unsigned getDeclRefExprAbbrev() const { return DeclRefExprAbbrev; } unsigned getCharacterLiteralAbbrev() const { return CharacterLiteralAbbrev; } @@ -609,11 +680,12 @@ public: void ReaderInitialized(ASTReader *Reader); void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II); void TypeRead(serialization::TypeIdx Idx, QualType T); - void DeclRead(serialization::DeclID ID, const Decl *D); void SelectorRead(serialization::SelectorID ID, Selector Sel); void MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinition *MD); - + void MacroVisible(IdentifierInfo *II); + void ModuleRead(serialization::SubmoduleID ID, Module *Mod); + // ASTMutationListener implementation. virtual void CompletedTagDefinition(const TagDecl *D); virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); @@ -626,6 +698,9 @@ public: virtual void StaticDataMemberInstantiated(const VarDecl *D); virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD); + virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt); }; /// \brief AST and semantic-analysis consumer that generates a @@ -633,12 +708,12 @@ public: class PCHGenerator : public SemaConsumer { const Preprocessor &PP; std::string OutputFile; - bool IsModule; + clang::Module *Module; std::string isysroot; raw_ostream *Out; Sema *SemaPtr; MemorizeStatCalls *StatCalls; // owned by the FileManager - std::vector<unsigned char> Buffer; + llvm::SmallVector<char, 128> Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; @@ -647,8 +722,8 @@ protected: const ASTWriter &getWriter() const { return Writer; } public: - PCHGenerator(const Preprocessor &PP, StringRef OutputFile, - bool IsModule, + PCHGenerator(const Preprocessor &PP, StringRef OutputFile, + clang::Module *Module, StringRef isysroot, raw_ostream *Out); ~PCHGenerator(); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h index 7f78320..f368a80 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h @@ -68,6 +68,16 @@ public: "Must insert keys in order."); Rep.push_back(Val); } + + void insertOrReplace(const value_type &Val) { + iterator I = std::lower_bound(Rep.begin(), Rep.end(), Val, Compare()); + if (I != Rep.end() && I->first == Val.first) { + I->second = Val.second; + return; + } + + Rep.insert(I, Val); + } typedef typename Representation::iterator iterator; typedef typename Representation::const_iterator const_iterator; diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h index 42b5a58..4c93c33 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h @@ -23,12 +23,13 @@ #include "llvm/Bitcode/BitstreamReader.h" #include <string> -namespace clang { +namespace clang { class DeclContext; +class Module; namespace serialization { - + /// \brief Specifies the kind of module that has been loaded. enum ModuleKind { MK_Module, ///< File is a module proper. @@ -39,9 +40,9 @@ enum ModuleKind { /// \brief Information about the contents of a DeclContext. struct DeclContextInfo { - DeclContextInfo() + DeclContextInfo() : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {} - + void *NameLookupTableData; // an ASTDeclContextNameLookupTable. const KindDeclIDPair *LexicalDecls; unsigned NumLexicalDecls; @@ -49,265 +50,303 @@ struct DeclContextInfo { /// \brief Information about a module that has been loaded by the ASTReader. /// -/// Each instance of the Module class corresponds to a single AST file, which -/// may be a precompiled header, precompiled preamble, a module, or an AST file -/// of some sort loaded as the main file, all of which are specific formulations of -/// the general notion of a "module". A module may depend on any number of +/// Each instance of the Module class corresponds to a single AST file, which +/// may be a precompiled header, precompiled preamble, a module, or an AST file +/// of some sort loaded as the main file, all of which are specific formulations +/// of the general notion of a "module". A module may depend on any number of /// other modules. -class Module { -public: - Module(ModuleKind Kind); - ~Module(); - +class ModuleFile { +public: + ModuleFile(ModuleKind Kind, unsigned Generation); + ~ModuleFile(); + // === General information === - + /// \brief The type of this module. ModuleKind Kind; - + /// \brief The file name of the module file. std::string FileName; - + /// \brief Whether this module has been directly imported by the /// user. bool DirectlyImported; + + /// \brief The generation of which this module file is a part. + unsigned Generation; /// \brief The memory buffer that stores the data associated with /// this AST file. - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - + OwningPtr<llvm::MemoryBuffer> Buffer; + /// \brief The size of this file, in bits. uint64_t SizeInBits; - + /// \brief The global bit offset (or base) of this module uint64_t GlobalBitOffset; - + /// \brief The bitstream reader from which we'll read the AST file. llvm::BitstreamReader StreamFile; - + /// \brief The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; - + /// \brief The source location where this module was first imported. SourceLocation ImportLoc; - + /// \brief The first source location in this module. SourceLocation FirstLoc; - + // === Source Locations === - + /// \brief Cursor used to read source location entries. llvm::BitstreamCursor SLocEntryCursor; - + /// \brief The number of source location entries in this AST file. unsigned LocalNumSLocEntries; - + /// \brief The base ID in the source manager's view of this module. int SLocEntryBaseID; - + /// \brief The base offset in the source manager's view of this module. unsigned SLocEntryBaseOffset; - + /// \brief Offsets for all of the source location entries in the /// AST file. const uint32_t *SLocEntryOffsets; - + /// \brief SLocEntries that we're going to preload. SmallVector<uint64_t, 4> PreloadSLocEntries; /// \brief The number of source location file entries in this AST file. unsigned LocalNumSLocFileEntries; - + /// \brief Offsets for all of the source location file entries in the /// AST file. const uint32_t *SLocFileOffsets; - + /// \brief Remapping table for source locations in this module. ContinuousRangeMap<uint32_t, int, 2> SLocRemap; - + // === Identifiers === - + /// \brief The number of identifiers in this AST file. unsigned LocalNumIdentifiers; - + /// \brief Offsets into the identifier table data. /// /// This array is indexed by the identifier ID (-1), and provides /// the offset into IdentifierTableData where the string data is /// stored. const uint32_t *IdentifierOffsets; - + /// \brief Base identifier ID for identifiers local to this module. serialization::IdentID BaseIdentifierID; - + /// \brief Remapping table for identifier IDs in this module. ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap; - + /// \brief Actual data for the on-disk hash table of identifiers. /// /// This pointer points into a memory buffer, where the on-disk hash /// table for identifiers actually lives. const char *IdentifierTableData; - + /// \brief A pointer to an on-disk hash table of opaque type /// IdentifierHashTable. void *IdentifierLookupTable; - + // === Macros === - + /// \brief The cursor to the start of the preprocessor block, which stores /// all of the macro definitions. llvm::BitstreamCursor MacroCursor; - + /// \brief The offset of the start of the set of defined macros. uint64_t MacroStartOffset; - + // === Detailed PreprocessingRecord === - - /// \brief The cursor to the start of the (optional) detailed preprocessing + + /// \brief The cursor to the start of the (optional) detailed preprocessing /// record block. llvm::BitstreamCursor PreprocessorDetailCursor; - + /// \brief The offset of the start of the preprocessor detail cursor. uint64_t PreprocessorDetailStartOffset; - - /// \brief Base preprocessed entity ID for preprocessed entities local to + + /// \brief Base preprocessed entity ID for preprocessed entities local to /// this module. serialization::PreprocessedEntityID BasePreprocessedEntityID; - + /// \brief Remapping table for preprocessed entity IDs in this module. ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap; - + const PPEntityOffset *PreprocessedEntityOffsets; unsigned NumPreprocessedEntities; - + // === Header search information === - + /// \brief The number of local HeaderFileInfo structures. unsigned LocalNumHeaderFileInfos; - - /// \brief Actual data for the on-disk hash table of header file + + /// \brief Actual data for the on-disk hash table of header file /// information. /// /// This pointer points into a memory buffer, where the on-disk hash /// table for header file information actually lives. const char *HeaderFileInfoTableData; - + /// \brief The on-disk hash table that contains information about each of /// the header files. void *HeaderFileInfoTable; - + /// \brief Actual data for the list of framework names used in the header /// search information. const char *HeaderFileFrameworkStrings; + + // === Submodule information === + /// \brief The number of submodules in this module. + unsigned LocalNumSubmodules; - // === Selectors === + /// \brief Base submodule ID for submodules local to this module. + serialization::SubmoduleID BaseSubmoduleID; + /// \brief Remapping table for submodule IDs in this module. + ContinuousRangeMap<uint32_t, int, 2> SubmoduleRemap; + + // === Selectors === + /// \brief The number of selectors new to this file. /// /// This is the number of entries in SelectorOffsets. unsigned LocalNumSelectors; - + /// \brief Offsets into the selector lookup table's data array /// where each selector resides. const uint32_t *SelectorOffsets; - + /// \brief Base selector ID for selectors local to this module. serialization::SelectorID BaseSelectorID; - + /// \brief Remapping table for selector IDs in this module. ContinuousRangeMap<uint32_t, int, 2> SelectorRemap; - + /// \brief A pointer to the character data that comprises the selector table /// /// The SelectorOffsets table refers into this memory. const unsigned char *SelectorLookupTableData; - + /// \brief A pointer to an on-disk hash table of opaque type /// ASTSelectorLookupTable. /// /// This hash table provides the IDs of all selectors, and the associated /// instance and factory methods. void *SelectorLookupTable; - + // === Declarations === - + /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It /// has read all the abbreviations at the start of the block and is ready to /// jump around with these in context. llvm::BitstreamCursor DeclsCursor; - + /// \brief The number of declarations in this AST file. unsigned LocalNumDecls; - + /// \brief Offset of each declaration within the bitstream, indexed /// by the declaration ID (-1). - const uint32_t *DeclOffsets; - + const DeclOffset *DeclOffsets; + /// \brief Base declaration ID for declarations local to this module. serialization::DeclID BaseDeclID; - + /// \brief Remapping table for declaration IDs in this module. ContinuousRangeMap<uint32_t, int, 2> DeclRemap; - + + /// \brief Mapping from the module files that this module file depends on + /// to the base declaration ID for that module as it is understood within this + /// module. + /// + /// This is effectively a reverse global-to-local mapping for declaration + /// IDs, so that we can interpret a true global ID (for this translation unit) + /// as a local ID (for this module file). + llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs; + /// \brief The number of C++ base specifier sets in this AST file. unsigned LocalNumCXXBaseSpecifiers; - + /// \brief Offset of each C++ base specifier set within the bitstream, /// indexed by the C++ base specifier set ID (-1). const uint32_t *CXXBaseSpecifiersOffsets; - + typedef llvm::DenseMap<const DeclContext *, DeclContextInfo> DeclContextInfosMap; - + /// \brief Information about the lexical and visible declarations /// for each DeclContext. DeclContextInfosMap DeclContextInfos; - typedef llvm::DenseMap<serialization::GlobalDeclID, - std::pair<serialization::LocalDeclID, serialization::LocalDeclID> > - ChainedObjCCategoriesMap; - /// \brief ObjC categories that got chained to an interface from another - /// module. - /// Key is the ID of the interface. - /// Value is a pair of linked category DeclIDs (head category, tail category). - ChainedObjCCategoriesMap ChainedObjCCategories; + /// \brief Array of file-level DeclIDs sorted by file. + const serialization::DeclID *FileSortedDecls; + + /// \brief Array of redeclaration chain location information within this + /// module file, sorted by the first declaration ID. + const serialization::LocalRedeclarationsInfo *RedeclarationsMap; + + /// \brief The number of redeclaration info entries in RedeclarationsMap. + unsigned LocalNumRedeclarationsInMap; - // === Types === + /// \brief The redeclaration chains for declarations local to this + /// module file. + SmallVector<uint64_t, 1> RedeclarationChains; + + /// \brief Array of category list location information within this + /// module file, sorted by the definition ID. + const serialization::ObjCCategoriesInfo *ObjCCategoriesMap; + /// \brief The number of redeclaration info entries in ObjCCategoriesMap. + unsigned LocalNumObjCCategoriesInMap; + + /// \brief The Objective-C category lists for categories known to this + /// module. + SmallVector<uint64_t, 1> ObjCCategories; + + // === Types === + /// \brief The number of types in this AST file. unsigned LocalNumTypes; - + /// \brief Offset of each type within the bitstream, indexed by the /// type ID, or the representation of a Type*. const uint32_t *TypeOffsets; - - /// \brief Base type ID for types local to this module as represented in + + /// \brief Base type ID for types local to this module as represented in /// the global type ID space. serialization::TypeID BaseTypeIndex; - + /// \brief Remapping table for type IDs in this module. ContinuousRangeMap<uint32_t, int, 2> TypeRemap; - + // === Miscellaneous === - + /// \brief Diagnostic IDs and their mappings that the user changed. SmallVector<uint64_t, 8> PragmaDiagMappings; - + /// \brief The AST stat cache installed for this file, if any. /// /// The dynamic type of this stat cache is always ASTStatCache void *StatCache; - + /// \brief List of modules which depend on this module - llvm::SetVector<Module *> ImportedBy; - + llvm::SetVector<ModuleFile *> ImportedBy; + /// \brief List of modules which this module depends on - llvm::SetVector<Module *> Imports; - + llvm::SetVector<ModuleFile *> Imports; + /// \brief Determine whether this module was directly imported at /// any point during translation. bool isDirectlyImported() const { return DirectlyImported; } - + /// \brief Dump debugging output for this module. void dump(); }; diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h index f86915a..6ff0640 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h @@ -27,10 +27,10 @@ namespace serialization { class ModuleManager { /// \brief The chain of AST files. The first entry is the one named by the /// user, the last one is the one that doesn't depend on anything further. - llvm::SmallVector<Module*, 2> Chain; + llvm::SmallVector<ModuleFile*, 2> Chain; /// \brief All loaded modules, indexed by name. - llvm::DenseMap<const FileEntry *, Module *> Modules; + llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; /// \brief FileManager that handles translating between filenames and /// FileEntry *. @@ -40,9 +40,9 @@ class ModuleManager { llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers; public: - typedef SmallVector<Module*, 2>::iterator ModuleIterator; - typedef SmallVector<Module*, 2>::const_iterator ModuleConstIterator; - typedef SmallVector<Module*, 2>::reverse_iterator ModuleReverseIterator; + typedef SmallVector<ModuleFile*, 2>::iterator ModuleIterator; + typedef SmallVector<ModuleFile*, 2>::const_iterator ModuleConstIterator; + typedef SmallVector<ModuleFile*, 2>::reverse_iterator ModuleReverseIterator; typedef std::pair<uint32_t, StringRef> ModuleOffset; ModuleManager(const FileSystemOptions &FSO); @@ -68,17 +68,17 @@ public: /// \brief Returns the primary module associated with the manager, that is, /// the first module loaded - Module &getPrimaryModule() { return *Chain[0]; } + ModuleFile &getPrimaryModule() { return *Chain[0]; } /// \brief Returns the primary module associated with the manager, that is, /// the first module loaded. - Module &getPrimaryModule() const { return *Chain[0]; } + ModuleFile &getPrimaryModule() const { return *Chain[0]; } /// \brief Returns the module associated with the given index - Module &operator[](unsigned Index) const { return *Chain[Index]; } + ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; } /// \brief Returns the module associated with the given name - Module *lookup(StringRef Name); + ModuleFile *lookup(StringRef Name); /// \brief Returns the in-memory (virtual file) buffer with the given name llvm::MemoryBuffer *lookupBuffer(StringRef Name); @@ -95,14 +95,16 @@ public: /// \param ImportedBy The module that is importing this module, or NULL if /// this module is imported directly by the user. /// + /// \param Generation The generation in which this module was loaded. + /// /// \param ErrorStr Will be set to a non-empty string if any errors occurred /// while trying to load the module. /// /// \return A pointer to the module that corresponds to this file name, /// and a boolean indicating whether the module was newly added. - std::pair<Module *, bool> - addModule(StringRef FileName, ModuleKind Type, Module *ImportedBy, - std::string &ErrorStr); + std::pair<ModuleFile *, bool> + addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy, + unsigned Generation, std::string &ErrorStr); /// \brief Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); @@ -125,7 +127,7 @@ public: /// /// \param UserData User data associated with the visitor object, which /// will be passed along to the visitor. - void visit(bool (*Visitor)(Module &M, void *UserData), void *UserData); + void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData); /// \brief Visit each of the modules with a depth-first traversal. /// @@ -143,7 +145,7 @@ public: /// /// \param UserData User data ssociated with the visitor object, /// which will be passed along to the user. - void visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, + void visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, void *UserData), void *UserData); diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h new file mode 100644 index 0000000..e63f814 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h @@ -0,0 +1,28 @@ +//===--- SerializationDiagnostic.h - Serialization Diagnostics -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SERIALIZATIONDIAGNOSTIC_H +#define LLVM_CLANG_SERIALIZATIONDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, +#define SERIALIZATIONSTART +#include "clang/Basic/DiagnosticSerializationKinds.inc" +#undef DIAG + NUM_BUILTIN_SERIALIZATION_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h new file mode 100644 index 0000000..9d4251b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h @@ -0,0 +1,24 @@ +//=--- CommonBugCategories.h - Provides common issue categories -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H +#define LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H + +// Common strings used for the "category" of many static analyzer issues. +namespace clang { + namespace ento { + namespace categories { + extern const char *CoreFoundationObjectiveC; + extern const char *MemoryCoreFoundationObjectiveC; + extern const char *UnixAPI; + } + } +} +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index bfb7ef8..2b699a8 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -20,10 +20,10 @@ #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ImmutableSet.h" -#include "llvm/ADT/SmallSet.h" -#include <list> +#include "llvm/ADT/DenseSet.h" namespace clang { @@ -49,9 +49,10 @@ class BugType; /// This class provides an interface through which checkers can create /// individual bug reports. -class BugReport { -public: +class BugReport : public llvm::ilist_node<BugReport> { +public: class NodeResolver { + virtual void anchor(); public: virtual ~NodeResolver() {} virtual const ExplodedNode* @@ -59,7 +60,8 @@ public: }; typedef const SourceRange *ranges_iterator; - typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator; + typedef SmallVector<BugReporterVisitor *, 8> VisitorList; + typedef VisitorList::iterator visitor_iterator; typedef SmallVector<StringRef, 2> ExtraTextList; protected: @@ -67,32 +69,65 @@ protected: friend class BugReportEquivClass; BugType& BT; + const Decl *DeclWithIssue; std::string ShortDescription; std::string Description; PathDiagnosticLocation Location; + PathDiagnosticLocation UniqueingLocation; const ExplodedNode *ErrorNode; SmallVector<SourceRange, 4> Ranges; ExtraTextList ExtraText; + + typedef llvm::DenseSet<SymbolRef> Symbols; + typedef llvm::DenseSet<const MemRegion *> Regions; + + /// A set of symbols that are registered with this report as being + /// "interesting", and thus used to help decide which diagnostics + /// to include when constructing the final path diagnostic. + Symbols interestingSymbols; + + /// A set of regions that are registered with this report as being + /// "interesting", and thus used to help decide which diagnostics + /// to include when constructing the final path diagnostic. + Regions interestingRegions; - // Not the most efficient data structure, but we use an ImmutableList for the - // Callbacks because it is safe to make additions to list during iteration. - llvm::ImmutableList<BugReporterVisitor*>::Factory F; - llvm::ImmutableList<BugReporterVisitor*> Callbacks; + /// A set of custom visitors which generate "event" diagnostics at + /// interesting points in the path. + VisitorList Callbacks; + + /// Used for ensuring the visitors are only added once. llvm::FoldingSet<BugReporterVisitor> CallbacksSet; + /// Used for clients to tell if the report's configuration has changed + /// since the last time they checked. + unsigned ConfigurationChangeToken; + public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), Description(desc), ErrorNode(errornode), - Callbacks(F.getEmptyList()) {} + : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), + ConfigurationChangeToken(0) {} BugReport(BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) - : BT(bt), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), Callbacks(F.getEmptyList()) {} + : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), + ErrorNode(errornode), ConfigurationChangeToken(0) {} BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) - : BT(bt), Description(desc), Location(l), ErrorNode(0), - Callbacks(F.getEmptyList()) {} + : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), + ConfigurationChangeToken(0) {} + + /// \brief Create a BugReport with a custom uniqueing location. + /// + /// The reports that have the same report location, description, bug type, and + /// ranges are uniqued - only one of the equivalent reports will be presented + /// to the user. This method allows to rest the location which should be used + /// for uniquing reports. For example, memory leaks checker, could set this to + /// the allocation site, rather then the location where the bug is reported. + BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, + PathDiagnosticLocation LocationToUnique) + : BT(bt), DeclWithIssue(0), Description(desc), + UniqueingLocation(LocationToUnique), + ErrorNode(errornode), ConfigurationChangeToken(0) {} virtual ~BugReport(); @@ -107,6 +142,28 @@ public: return ShortDescription.empty() ? Description : ShortDescription; } + void markInteresting(SymbolRef sym); + void markInteresting(const MemRegion *R); + void markInteresting(SVal V); + + bool isInteresting(SymbolRef sym) const; + bool isInteresting(const MemRegion *R) const; + bool isInteresting(SVal V) const; + + unsigned getConfigurationChangeToken() const { + return ConfigurationChangeToken; + } + + /// Return the canonical declaration, be it a method or class, where + /// this issue semantically occurred. + const Decl *getDeclWithIssue() const; + + /// Specifically set the Decl where an issue occurred. This isn't necessary + /// for BugReports that cover a path as it will be automatically inferred. + void setDeclWithIssue(const Decl *declWithIssue) { + DeclWithIssue = declWithIssue; + } + /// \brief This allows for addition of meta data to the diagnostic. /// /// Currently, only the HTMLDiagnosticClient knows how to display it. @@ -162,13 +219,38 @@ public: virtual void Profile(llvm::FoldingSetNodeID& hash) const; }; +} // end ento namespace +} // end clang namespace + +namespace llvm { + template<> struct ilist_traits<clang::ento::BugReport> + : public ilist_default_traits<clang::ento::BugReport> { + clang::ento::BugReport *createSentinel() const { + return static_cast<clang::ento::BugReport *>(&Sentinel); + } + void destroySentinel(clang::ento::BugReport *) const {} + + clang::ento::BugReport *provideInitialHead() const { + return createSentinel(); + } + clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const { + return createSentinel(); + } + private: + mutable ilist_half_node<clang::ento::BugReport> Sentinel; + }; +} + +namespace clang { +namespace ento { + //===----------------------------------------------------------------------===// // BugTypes (collections of related reports). //===----------------------------------------------------------------------===// class BugReportEquivClass : public llvm::FoldingSetNode { /// List of *owned* BugReport objects. - std::list<BugReport*> Reports; + llvm::ilist<BugReport> Reports; friend class BugReporter; void AddReport(BugReport* R) { Reports.push_back(R); } @@ -178,36 +260,17 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const { assert(!Reports.empty()); - (*Reports.begin())->Profile(ID); + Reports.front().Profile(ID); } - class iterator { - std::list<BugReport*>::iterator impl; - public: - iterator(std::list<BugReport*>::iterator i) : impl(i) {} - iterator &operator++() { ++impl; return *this; } - bool operator==(const iterator &I) const { return I.impl == impl; } - bool operator!=(const iterator &I) const { return I.impl != impl; } - BugReport* operator*() const { return *impl; } - BugReport* operator->() const { return *impl; } - }; + typedef llvm::ilist<BugReport>::iterator iterator; + typedef llvm::ilist<BugReport>::const_iterator const_iterator; - class const_iterator { - std::list<BugReport*>::const_iterator impl; - public: - const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {} - const_iterator &operator++() { ++impl; return *this; } - bool operator==(const const_iterator &I) const { return I.impl == impl; } - bool operator!=(const const_iterator &I) const { return I.impl != impl; } - const BugReport* operator*() const { return *impl; } - const BugReport* operator->() const { return *impl; } - }; - - iterator begin() { return iterator(Reports.begin()); } - iterator end() { return iterator(Reports.end()); } + iterator begin() { return Reports.begin(); } + iterator end() { return Reports.end(); } - const_iterator begin() const { return const_iterator(Reports.begin()); } - const_iterator end() const { return const_iterator(Reports.end()); } + const_iterator begin() const { return Reports.begin(); } + const_iterator end() const { return Reports.end(); } }; //===----------------------------------------------------------------------===// @@ -294,34 +357,22 @@ public: /// reports. void EmitReport(BugReport *R); - void EmitBasicReport(StringRef BugName, StringRef BugStr, - PathDiagnosticLocation Loc, - SourceRange* RangeBeg, unsigned NumRanges); - - void EmitBasicReport(StringRef BugName, StringRef BugCategory, + void EmitBasicReport(const Decl *DeclWithIssue, + StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, SourceRange* RangeBeg, unsigned NumRanges); - - void EmitBasicReport(StringRef BugName, StringRef BugStr, - PathDiagnosticLocation Loc) { - EmitBasicReport(BugName, BugStr, Loc, 0, 0); - } - - void EmitBasicReport(StringRef BugName, StringRef BugCategory, + void EmitBasicReport(const Decl *DeclWithIssue, + StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc) { - EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0); - } - - void EmitBasicReport(StringRef BugName, StringRef BugStr, - PathDiagnosticLocation Loc, SourceRange R) { - EmitBasicReport(BugName, BugStr, Loc, &R, 1); + EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0); } - void EmitBasicReport(StringRef BugName, StringRef Category, + void EmitBasicReport(const Decl *DeclWithIssue, + StringRef BugName, StringRef Category, StringRef BugStr, PathDiagnosticLocation Loc, SourceRange R) { - EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1); + EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1); } static bool classof(const BugReporter* R) { return true; } @@ -337,7 +388,6 @@ private: // FIXME: Get rid of GRBugReporter. It's the wrong abstraction. class GRBugReporter : public BugReporter { ExprEngine& Eng; - llvm::SmallSet<SymbolRef, 10> NotableSymbols; public: GRBugReporter(BugReporterData& d, ExprEngine& eng) : BugReporter(d, GRBugReporterKind), Eng(eng) {} @@ -359,14 +409,6 @@ public: virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic, SmallVectorImpl<BugReport*> &bugReports); - void addNotableSymbol(SymbolRef Sym) { - NotableSymbols.insert(Sym); - } - - bool isNotable(SymbolRef Sym) const { - return (bool) NotableSymbols.count(Sym); - } - /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { return R->getKind() == GRBugReporterKind; @@ -374,6 +416,7 @@ public: }; class BugReporterContext { + virtual void anchor(); GRBugReporter &BR; public: BugReporterContext(GRBugReporter& br) : BR(br) {} @@ -384,16 +427,6 @@ public: ExplodedGraph &getGraph() { return BR.getGraph(); } - void addNotableSymbol(SymbolRef Sym) { - // FIXME: For now forward to GRBugReporter. - BR.addNotableSymbol(Sym); - } - - bool isNotable(SymbolRef Sym) const { - // FIXME: For now forward to GRBugReporter. - return BR.isNotable(Sym); - } - ProgramStateManager& getStateManager() { return BR.getStateManager(); } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 41c0a3a..7e665ce 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -28,10 +28,28 @@ class ExplodedNode; class MemRegion; class PathDiagnosticPiece; +/// \brief BugReporterVisitors are used to add custom diagnostics along a path. +/// +/// Custom visitors should subclass the BugReporterVisitorImpl class for a +/// default implementation of the clone() method. +/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the +/// default implementation of clone() will NOT do the right thing, and you +/// will have to provide your own implementation.) class BugReporterVisitor : public llvm::FoldingSetNode { public: virtual ~BugReporterVisitor(); + /// \brief Returns a copy of this BugReporter. + /// + /// Custom BugReporterVisitors should not override this method directly. + /// Instead, they should inherit from BugReporterVisitorImpl and provide + /// a protected or public copy constructor. + /// + /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the + /// default implementation of clone() will NOT do the right thing, and you + /// will have to provide your own implementation.) + virtual BugReporterVisitor *clone() const = 0; + /// \brief Return a diagnostic piece which should be associated with the /// given node. /// @@ -61,7 +79,24 @@ public: }; -class FindLastStoreBRVisitor : public BugReporterVisitor { +/// This class provides a convenience implementation for clone() using the +/// Curiously-Recurring Template Pattern. If you are implementing a custom +/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public +/// or protected copy constructor. +/// +/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the +/// default implementation of clone() will NOT do the right thing, and you +/// will have to provide your own implementation.) +template <class DERIVED> +class BugReporterVisitorImpl : public BugReporterVisitor { + virtual BugReporterVisitor *clone() const { + return new DERIVED(*static_cast<const DERIVED *>(this)); + } +}; + +class FindLastStoreBRVisitor + : public BugReporterVisitorImpl<FindLastStoreBRVisitor> +{ const MemRegion *R; SVal V; bool satisfied; @@ -94,7 +129,9 @@ public: BugReport &BR); }; -class TrackConstraintBRVisitor : public BugReporterVisitor { +class TrackConstraintBRVisitor + : public BugReporterVisitorImpl<TrackConstraintBRVisitor> +{ DefinedSVal Constraint; const bool Assumption; bool isSatisfied; @@ -111,7 +148,9 @@ public: BugReport &BR); }; -class NilReceiverBRVisitor : public BugReporterVisitor { +class NilReceiverBRVisitor + : public BugReporterVisitorImpl<NilReceiverBRVisitor> +{ public: void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; @@ -125,50 +164,71 @@ public: }; /// Visitor that tries to report interesting diagnostics from conditions. -class ConditionBRVisitor : public BugReporterVisitor { +class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { public: void Profile(llvm::FoldingSetNodeID &ID) const { static int x = 0; ID.AddPointer(&x); } + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *Prev, BugReporterContext &BRC, BugReport &BR); + PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR); + PathDiagnosticPiece *VisitTerminator(const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk, const CFGBlock *dstBlk, + BugReport &R, BugReporterContext &BRC); PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, bool tookTrue, BugReporterContext &BRC, - const LocationContext *LC); + BugReport &R, + const ExplodedNode *N); PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR, const bool tookTrue, BugReporterContext &BRC, - const LocationContext *LC); + BugReport &R, + const ExplodedNode *N); PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr, const bool tookTrue, BugReporterContext &BRC, - const LocationContext *LC); + BugReport &R, + const ExplodedNode *N); + + PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString, + const Expr *CondVarExpr, + const bool tookTrue, + BugReporterContext &BRC, + BugReport &R, + const ExplodedNode *N); bool patternMatch(const Expr *Ex, llvm::raw_ostream &Out, - BugReporterContext &BRC); + BugReporterContext &BRC, + BugReport &R, + const ExplodedNode *N, + llvm::Optional<bool> &prunable); }; - + namespace bugreporter { BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N, - const Stmt *S); + const Stmt *S, + BugReport *R); const Stmt *GetDerefExpr(const ExplodedNode *N); const Stmt *GetDenomExpr(const ExplodedNode *N); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 78067cd..cb49122 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -49,6 +49,7 @@ public: }; class BuiltinBug : public BugType { + virtual void anchor(); const std::string desc; public: BuiltinBug(const char *name, const char *description) diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 406be3c..5a8a1c7 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -14,9 +14,12 @@ #ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H #define LLVM_CLANG_PATH_DIAGNOSTIC_H -#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Analysis/ProgramPoint.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/Optional.h" #include <deque> #include <iterator> #include <string> @@ -24,7 +27,7 @@ namespace clang { -class AnalysisContext; +class AnalysisDeclContext; class BinaryOperator; class CompoundStmt; class Decl; @@ -38,6 +41,8 @@ class Stmt; namespace ento { class ExplodedNode; +class SymExpr; +typedef const SymExpr* SymbolRef; //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. @@ -46,33 +51,34 @@ class ExplodedNode; class PathDiagnostic; class PathDiagnosticConsumer { + virtual void anchor(); public: - PathDiagnosticConsumer() {} + PathDiagnosticConsumer() : flushed(false) {} + virtual ~PathDiagnosticConsumer(); + + void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade); + + virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, + SmallVectorImpl<std::string> *FilesMade) + = 0; - virtual ~PathDiagnosticConsumer() {} - - virtual void - FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade = 0) = 0; - - void FlushDiagnostics(SmallVectorImpl<std::string> &FilesMade) { - FlushDiagnostics(&FilesMade); - } - virtual StringRef getName() const = 0; - void HandlePathDiagnostic(const PathDiagnostic* D); + void HandlePathDiagnostic(PathDiagnostic *D); enum PathGenerationScheme { Minimal, Extensive }; virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } virtual bool supportsAllBlockEdges() const { return false; } virtual bool useVerboseDescription() const { return true; } + + /// Return true if the PathDiagnosticConsumer supports individual + /// PathDiagnostics that span multiple files. + virtual bool supportsCrossFileDiagnostics() const { return false; } protected: - /// The actual logic for handling path diagnostics, as implemented - /// by subclasses of PathDiagnosticConsumer. - virtual void HandlePathDiagnosticImpl(const PathDiagnostic* D) = 0; - + bool flushed; + llvm::FoldingSet<PathDiagnostic> Diags; }; //===----------------------------------------------------------------------===// @@ -89,8 +95,8 @@ public: PathDiagnosticRange() : isPoint(false) {} }; -typedef llvm::PointerUnion<const LocationContext*, AnalysisContext*> - LocationOrAnalysisContext; +typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*> + LocationOrAnalysisDeclContext; class PathDiagnosticLocation { private: @@ -111,10 +117,10 @@ private: FullSourceLoc genLocation(SourceLocation L = SourceLocation(), - LocationOrAnalysisContext LAC = (AnalysisContext*)0) const; + LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; PathDiagnosticRange - genRange(LocationOrAnalysisContext LAC = (AnalysisContext*)0) const; + genRange(LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; public: /// Create an invalid location. @@ -124,10 +130,11 @@ public: /// Create a location corresponding to the given statement. PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, - LocationOrAnalysisContext lac) + LocationOrAnalysisDeclContext lac) : K(StmtK), S(s), D(0), SM(&sm), Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { + assert(S); assert(Loc.isValid()); assert(Range.isValid()); } @@ -136,6 +143,7 @@ public: PathDiagnosticLocation(const Decl *d, const SourceManager &sm) : K(DeclK), S(0), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) { + assert(D); assert(Loc.isValid()); assert(Range.isValid()); } @@ -153,7 +161,7 @@ public: /// Create a location for the beginning of the statement. static PathDiagnosticLocation createBegin(const Stmt *S, const SourceManager &SM, - const LocationOrAnalysisContext LAC); + const LocationOrAnalysisDeclContext LAC); /// Create the location for the operator of the binary expression. /// Assumes the statement has a valid location. @@ -260,14 +268,13 @@ public: // Path "pieces" for path-sensitive diagnostics. //===----------------------------------------------------------------------===// -class PathDiagnosticPiece { +class PathDiagnosticPiece : public RefCountedBaseVPTR { public: - enum Kind { ControlFlow, Event, Macro }; + enum Kind { ControlFlow, Event, Macro, Call }; enum DisplayHint { Above, Below }; private: const std::string str; - std::vector<FixItHint> FixItHints; const Kind kind; const DisplayHint Hint; std::vector<SourceRange> ranges; @@ -308,10 +315,6 @@ public: ranges.push_back(SourceRange(B,E)); } - void addFixItHint(const FixItHint& Hint) { - FixItHints.push_back(Hint); - } - typedef const SourceRange* range_iterator; range_iterator ranges_begin() const { @@ -322,23 +325,19 @@ public: return ranges_begin() + ranges.size(); } - typedef const FixItHint *fixit_iterator; - - fixit_iterator fixit_begin() const { - return FixItHints.empty()? 0 : &FixItHints[0]; - } - - fixit_iterator fixit_end() const { - return FixItHints.empty()? 0 - : &FixItHints[0] + FixItHints.size(); - } - static inline bool classof(const PathDiagnosticPiece *P) { return true; } virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; + + +class PathPieces : + public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > { +public: + ~PathPieces(); +}; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { private: @@ -360,20 +359,170 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; +/// \brief Interface for classes constructing Stack hints. +/// +/// If a PathDiagnosticEvent occurs in a different frame than the final +/// diagnostic the hints can be used to summarise the effect of the call. +class StackHintGenerator { +public: + virtual ~StackHintGenerator() = 0; + + /// \brief Construct the Diagnostic message for the given ExplodedNode. + virtual std::string getMessage(const ExplodedNode *N) = 0; +}; + +/// \brief Constructs a Stack hint for the given symbol. +/// +/// The class knows how to construct the stack hint message based on +/// traversing the CallExpr associated with the call and checking if the given +/// symbol is returned or is one of the arguments. +/// The hint can be customized by redefining 'getMessageForX()' methods. +class StackHintGeneratorForSymbol : public StackHintGenerator { +private: + SymbolRef Sym; + std::string Msg; + +public: + StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} + virtual ~StackHintGeneratorForSymbol() {} + + /// \brief Search the call expression for the symbol Sym and dispatch the + /// 'getMessageForX()' methods to construct a specific message. + virtual std::string getMessage(const ExplodedNode *N); + + /// Prints the ordinal form of the given integer, + /// only valid for ValNo : ValNo > 0. + void printOrdinal(unsigned ValNo, llvm::raw_svector_ostream &Out); + + /// Produces the message of the following form: + /// 'Msg via Nth parameter' + virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { + return Msg; + } + virtual std::string getMessageForSymbolNotFound() { + return Msg; + } +}; + class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { + llvm::Optional<bool> IsPrunable; + + /// If the event occurs in a different frame than the final diagnostic, + /// supply a message that will be used to construct an extra hint on the + /// returns from all the calls on the stack from this event to the final + /// diagnostic. + llvm::OwningPtr<StackHintGenerator> CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, - StringRef s, bool addPosRange = true) - : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} + StringRef s, bool addPosRange = true, + StackHintGenerator *stackHint = 0) + : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), + CallStackHint(stackHint) {} ~PathDiagnosticEventPiece(); + /// Mark the diagnostic piece as being potentially prunable. This + /// flag may have been previously set, at which point it will not + /// be reset unless one specifies to do so. + void setPrunable(bool isPrunable, bool override = false) { + if (IsPrunable.hasValue() && !override) + return; + IsPrunable = isPrunable; + } + + /// Return true if the diagnostic piece is prunable. + bool isPrunable() const { + return IsPrunable.hasValue() ? IsPrunable.getValue() : false; + } + + bool hasCallStackHint() { + return (CallStackHint != 0); + } + + /// Produce the hint for the given node. The node contains + /// information about the call for which the diagnostic can be generated. + std::string getCallStackMessage(const ExplodedNode *N) { + if (CallStackHint) + return CallStackHint->getMessage(N); + return ""; + } + static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; } }; +class PathDiagnosticCallPiece : public PathDiagnosticPiece { + PathDiagnosticCallPiece(const Decl *callerD, + const PathDiagnosticLocation &callReturnPos) + : PathDiagnosticPiece(Call), Caller(callerD), Callee(0), + NoExit(false), callReturn(callReturnPos) {} + + PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) + : PathDiagnosticPiece(Call), Caller(caller), Callee(0), + NoExit(true), path(oldPath) {} + + const Decl *Caller; + const Decl *Callee; + + // Flag signifying that this diagnostic has only call enter and no matching + // call exit. + bool NoExit; + + // The custom string, which should appear after the call Return Diagnostic. + // TODO: Should we allow multiple diagnostics? + std::string CallStackMessage; + +public: + PathDiagnosticLocation callEnter; + PathDiagnosticLocation callEnterWithin; + PathDiagnosticLocation callReturn; + PathPieces path; + + virtual ~PathDiagnosticCallPiece(); + + const Decl *getCaller() const { return Caller; } + + const Decl *getCallee() const { return Callee; } + void setCallee(const CallEnter &CE, const SourceManager &SM); + + bool hasCallStackMessage() { return !CallStackMessage.empty(); } + void setCallStackMessage(StringRef st) { + CallStackMessage = st; + } + + virtual PathDiagnosticLocation getLocation() const { + return callEnter; + } + + IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const; + IntrusiveRefCntPtr<PathDiagnosticEventPiece> + getCallEnterWithinCallerEvent() const; + IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const; + + virtual void flattenLocations() { + callEnter.flatten(); + callReturn.flatten(); + for (PathPieces::iterator I = path.begin(), + E = path.end(); I != E; ++I) (*I)->flattenLocations(); + } + + static PathDiagnosticCallPiece *construct(const ExplodedNode *N, + const CallExit &CE, + const SourceManager &SM); + + static PathDiagnosticCallPiece *construct(PathPieces &pieces, + const Decl *caller); + + virtual void Profile(llvm::FoldingSetNodeID &ID) const; + + static inline bool classof(const PathDiagnosticPiece *P) { + return P->getKind() == Call; + } +}; + class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { std::vector<PathDiagnosticLocationPair> LPairs; public: @@ -431,30 +580,22 @@ public: }; class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { - std::vector<PathDiagnosticPiece*> SubPieces; public: PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos) : PathDiagnosticSpotPiece(pos, "", Macro) {} ~PathDiagnosticMacroPiece(); + PathPieces subPieces; + bool containsEvent() const; - void push_back(PathDiagnosticPiece *P) { SubPieces.push_back(P); } - - typedef std::vector<PathDiagnosticPiece*>::iterator iterator; - iterator begin() { return SubPieces.begin(); } - iterator end() { return SubPieces.end(); } - virtual void flattenLocations() { PathDiagnosticSpotPiece::flattenLocations(); - for (iterator I=begin(), E=end(); I!=E; ++I) (*I)->flattenLocations(); + for (PathPieces::iterator I = subPieces.begin(), + E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); } - typedef std::vector<PathDiagnosticPiece*>::const_iterator const_iterator; - const_iterator begin() const { return SubPieces.begin(); } - const_iterator end() const { return SubPieces.end(); } - static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Macro; } @@ -466,17 +607,41 @@ public: /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces, /// each which represent the pieces of the path. class PathDiagnostic : public llvm::FoldingSetNode { - std::deque<PathDiagnosticPiece*> path; - unsigned Size; + const Decl *DeclWithIssue; std::string BugType; std::string Desc; std::string Category; std::deque<std::string> OtherDesc; - + PathPieces pathImpl; + llvm::SmallVector<PathPieces *, 3> pathStack; + + PathDiagnostic(); // Do not implement. public: - PathDiagnostic(); + const PathPieces &path; + + /// Return the path currently used by builders for constructing the + /// PathDiagnostic. + PathPieces &getActivePath() { + if (pathStack.empty()) + return pathImpl; + return *pathStack.back(); + } + + /// Return a mutable version of 'path'. + PathPieces &getMutablePieces() { + return pathImpl; + } + + /// Return the unrolled size of the path. + unsigned full_size(); - PathDiagnostic(StringRef bugtype, StringRef desc, + void pushActivePath(PathPieces *p) { pathStack.push_back(p); } + void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); } + + // PathDiagnostic(); + PathDiagnostic(const Decl *DeclWithIssue, + StringRef bugtype, + StringRef desc, StringRef category); ~PathDiagnostic(); @@ -485,115 +650,26 @@ public: StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } + /// Return the semantic context where an issue occurred. If the + /// issue occurs along a path, this represents the "central" area + /// where the bug manifests. + const Decl *getDeclWithIssue() const { return DeclWithIssue; } + typedef std::deque<std::string>::const_iterator meta_iterator; meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } void addMeta(StringRef s) { OtherDesc.push_back(s); } - PathDiagnosticLocation getLocation() const { - assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic."); - return rbegin()->getLocation(); - } - - void push_front(PathDiagnosticPiece *piece) { - assert(piece); - path.push_front(piece); - ++Size; - } - - void push_back(PathDiagnosticPiece *piece) { - assert(piece); - path.push_back(piece); - ++Size; - } - - PathDiagnosticPiece *back() { - return path.back(); - } - - const PathDiagnosticPiece *back() const { - return path.back(); - } - - unsigned size() const { return Size; } - bool empty() const { return Size == 0; } - - void resetPath(bool deletePieces = true); - - class iterator { - public: - typedef std::deque<PathDiagnosticPiece*>::iterator ImplTy; - - typedef PathDiagnosticPiece value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - private: - ImplTy I; - - public: - iterator(const ImplTy& i) : I(i) {} - - bool operator==(const iterator &X) const { return I == X.I; } - bool operator!=(const iterator &X) const { return I != X.I; } - - PathDiagnosticPiece& operator*() const { return **I; } - PathDiagnosticPiece *operator->() const { return *I; } - - iterator &operator++() { ++I; return *this; } - iterator &operator--() { --I; return *this; } - }; - - class const_iterator { - public: - typedef std::deque<PathDiagnosticPiece*>::const_iterator ImplTy; - - typedef const PathDiagnosticPiece value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - private: - ImplTy I; - - public: - const_iterator(const ImplTy& i) : I(i) {} - - bool operator==(const const_iterator &X) const { return I == X.I; } - bool operator!=(const const_iterator &X) const { return I != X.I; } - - reference operator*() const { return **I; } - pointer operator->() const { return *I; } - - const_iterator &operator++() { ++I; return *this; } - const_iterator &operator--() { --I; return *this; } - }; - - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - // forward iterator creation methods. - - iterator begin() { return path.begin(); } - iterator end() { return path.end(); } - - const_iterator begin() const { return path.begin(); } - const_iterator end() const { return path.end(); } - - // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + PathDiagnosticLocation getLocation() const; void flattenLocations() { - for (iterator I = begin(), E = end(); I != E; ++I) I->flattenLocations(); + for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); + I != E; ++I) (*I)->flattenLocations(); } void Profile(llvm::FoldingSetNodeID &ID) const; + + void FullProfile(llvm::FoldingSetNodeID &ID) const; }; } // end GR namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h index 1e4edeb..76d8c15 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -199,9 +199,9 @@ public: class EndPath { template <typename CHECKER> - static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, - ExprEngine &Eng) { - ((const CHECKER *)checker)->checkEndPath(B, Eng); + static void _checkEndPath(void *checker, + CheckerContext &C) { + ((const CHECKER *)checker)->checkEndPath(C); } public: @@ -214,9 +214,9 @@ public: class BranchCondition { template <typename CHECKER> - static void _checkBranchCondition(void *checker, const Stmt *condition, - BranchNodeBuilder &B, ExprEngine &Eng) { - ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); + static void _checkBranchCondition(void *checker, const Stmt *Condition, + CheckerContext & C) { + ((const CHECKER *)checker)->checkBranchCondition(Condition, C); } public: @@ -230,7 +230,7 @@ public: class LiveSymbols { template <typename CHECKER> - static void _checkLiveSymbols(void *checker, const ProgramState *state, + static void _checkLiveSymbols(void *checker, ProgramStateRef state, SymbolReaper &SR) { ((const CHECKER *)checker)->checkLiveSymbols(state, SR); } @@ -260,18 +260,19 @@ public: class RegionChanges { template <typename CHECKER> - static const ProgramState * + static ProgramStateRef _checkRegionChanges(void *checker, - const ProgramState *state, + ProgramStateRef state, const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> Explicits, - ArrayRef<const MemRegion *> Regions) { + ArrayRef<const MemRegion *> Regions, + const CallOrObjCMessage *Call) { return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, - Explicits, Regions); + Explicits, Regions, Call); } template <typename CHECKER> static bool _wantsRegionChangeUpdate(void *checker, - const ProgramState *state) { + ProgramStateRef state) { return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); } @@ -306,8 +307,8 @@ namespace eval { class Assume { template <typename CHECKER> - static const ProgramState *_evalAssume(void *checker, - const ProgramState *state, + static ProgramStateRef _evalAssume(void *checker, + ProgramStateRef state, const SVal &cond, bool assumption) { return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); @@ -359,7 +360,7 @@ public: StringRef getTagDescription() const; /// See CheckerManager::runCheckersForPrintState. - virtual void printState(raw_ostream &Out, const ProgramState *State, + virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const { } }; @@ -370,7 +371,8 @@ template <typename CHECK1, typename CHECK2=check::_VoidCheck, typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, - typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck> + typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, + typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck> class Checker; template <> @@ -379,9 +381,10 @@ class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck> + check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> : public CheckerBase { + virtual void anchor(); public: static void _register(void *checker, CheckerManager &mgr) { } }; @@ -389,19 +392,20 @@ public: template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, - typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16> + typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, + typename CHECK17,typename CHECK18> class Checker : public CHECK1, public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, - CHECK16> { + CHECK16,CHECK17,CHECK18> { public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { CHECK1::_register(checker, mgr); Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, - CHECK16>::_register(checker, mgr); + CHECK16,CHECK17,CHECK18>::_register(checker, mgr); } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index e3e4c49..d215f99 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "clang/Analysis/ProgramPoint.h" #include <vector> namespace clang { @@ -38,8 +39,8 @@ namespace ento { class ExplodedNodeSet; class ExplodedGraph; class ProgramState; - class EndOfFunctionNodeBuilder; - class BranchNodeBuilder; + class NodeBuilder; + struct NodeBuilderContext; class MemRegion; class SymbolReaper; @@ -51,6 +52,19 @@ public: template <typename T> class CheckerFn; +template <typename RET, typename P1, typename P2, typename P3, typename P4, + typename P5> +class CheckerFn<RET(P1, P2, P3, P4, P5)> { + typedef RET (*Func)(void *, P1, P2, P3, P4, P5); + Func Fn; +public: + CheckerBase *Checker; + CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } + RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { + return Fn(Checker, p1, p2, p3, p4, p5); + } +}; + template <typename RET, typename P1, typename P2, typename P3, typename P4> class CheckerFn<RET(P1, P2, P3, P4)> { typedef RET (*Func)(void *, P1, P2, P3, P4); @@ -114,7 +128,7 @@ public: void finishedCheckerRegistration(); - const LangOptions &getLangOptions() const { return LangOpts; } + const LangOptions &getLangOpts() const { return LangOpts; } typedef CheckerBase *CheckerRef; typedef const void *CheckerTag; @@ -179,14 +193,16 @@ public: void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, - ExprEngine &Eng) { - runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng); + ExprEngine &Eng, + bool wasInlined = false) { + runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); } /// \brief Run checkers for visiting Stmts. void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - const Stmt *S, ExprEngine &Eng); + const Stmt *S, ExprEngine &Eng, + bool wasInlined = false); /// \brief Run checkers for pre-visiting obj-c messages. void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, @@ -213,33 +229,39 @@ public: /// \brief Run checkers for load/store of a location. void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - SVal location, bool isLoad, - const Stmt *S, + SVal location, + bool isLoad, + const Stmt *NodeEx, + const Stmt *BoundEx, ExprEngine &Eng); /// \brief Run checkers for binding of a value to a location. void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, - const Stmt *S, ExprEngine &Eng); + const Stmt *S, ExprEngine &Eng, + ProgramPoint::Kind PointKind); /// \brief Run checkers for end of analysis. void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng); /// \brief Run checkers for end of path. - void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng); + void runCheckersForEndPath(NodeBuilderContext &BC, + ExplodedNodeSet &Dst, + ExprEngine &Eng); /// \brief Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, - BranchNodeBuilder &B, ExprEngine &Eng); + ExplodedNodeSet &Dst, ExplodedNode *Pred, + ExprEngine &Eng); /// \brief Run checkers for live symbols. /// /// Allows modifying SymbolReaper object. For example, checkers can explicitly /// register symbols of interest as live. These symbols will not be marked /// dead and removed. - void runCheckersForLiveSymbols(const ProgramState *state, + void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper); /// \brief Run checkers for dead symbols. @@ -253,7 +275,7 @@ public: ExprEngine &Eng); /// \brief True if at least one checker wants to check region changes. - bool wantsRegionChangeUpdate(const ProgramState *state); + bool wantsRegionChangeUpdate(ProgramStateRef state); /// \brief Run checkers for region changes. /// @@ -264,15 +286,18 @@ public: /// For example, in the case of a function call, these would be arguments. /// \param Regions The transitive closure of accessible regions, /// i.e. all regions that may have been touched by this change. - const ProgramState * - runCheckersForRegionChanges(const ProgramState *state, + /// \param The call expression wrapper if the regions are invalidated by a + /// call. + ProgramStateRef + runCheckersForRegionChanges(ProgramStateRef state, const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions); + ArrayRef<const MemRegion *> Regions, + const CallOrObjCMessage *Call); /// \brief Run checkers for handling assumptions on symbolic values. - const ProgramState *runCheckersForEvalAssume(const ProgramState *state, - SVal Cond, bool Assumption); + ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, + SVal Cond, bool Assumption); /// \brief Run checkers for evaluating a call. void runCheckersForEvalCall(ExplodedNodeSet &Dst, @@ -293,7 +318,7 @@ public: /// \param State The state being printed /// \param NL The preferred representation of a newline. /// \param Sep The preferred separator between different kinds of data. - void runCheckersForPrintState(raw_ostream &Out, const ProgramState *State, + void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep); //===----------------------------------------------------------------------===// @@ -320,7 +345,8 @@ public: typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)> CheckObjCMessageFunc; - typedef CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S, + typedef CheckerFn<void (const SVal &location, bool isLoad, + const Stmt *S, CheckerContext &)> CheckLocationFunc; @@ -331,26 +357,27 @@ public: typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> CheckEndAnalysisFunc; - typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)> + typedef CheckerFn<void (CheckerContext &)> CheckEndPathFunc; - typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)> + typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckBranchConditionFunc; typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> CheckDeadSymbolsFunc; - typedef CheckerFn<void (const ProgramState *,SymbolReaper &)> CheckLiveSymbolsFunc; + typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; - typedef CheckerFn<const ProgramState * (const ProgramState *, + typedef CheckerFn<ProgramStateRef (ProgramStateRef, const StoreManager::InvalidatedSymbols *symbols, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions)> + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const CallOrObjCMessage *Call)> CheckRegionChangesFunc; - typedef CheckerFn<bool (const ProgramState *)> WantsRegionChangeUpdateFunc; + typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; - typedef CheckerFn<const ProgramState * (const ProgramState *, + typedef CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, bool assumption)> EvalAssumeFunc; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h index b59c14d..1452d45 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h @@ -107,7 +107,9 @@ public: /// checker does not require any custom initialization. template <class T> void addChecker(StringRef fullName, StringRef desc) { - addChecker(&initializeManager<T>, fullName, desc); + // Avoid MSVC's Compiler Error C2276: + // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx + addChecker(&CheckerRegistry::initializeManager<T>, fullName, desc); } /// Initializes a CheckerManager by calling the initialization functions for diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index d1f5a7d..65be3a4 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -32,6 +32,10 @@ createPlistDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP, PathDiagnosticConsumer *SubPD = 0); PathDiagnosticConsumer* +createPlistMultiFileDiagnosticConsumer(const std::string& prefix, + const Preprocessor &PP); + +PathDiagnosticConsumer* createTextPathDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 6c93f59..3cbecf7 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -31,14 +31,14 @@ namespace ento { class CheckerManager; class AnalysisManager : public BugReporterData { - AnalysisContextManager AnaCtxMgr; - LocationContextManager LocCtxMgr; + virtual void anchor(); + AnalysisDeclContextManager AnaCtxMgr; ASTContext &Ctx; DiagnosticsEngine &Diags; - const LangOptions &LangInfo; + const LangOptions &LangOpts; - llvm::OwningPtr<PathDiagnosticConsumer> PD; + OwningPtr<PathDiagnosticConsumer> PD; // Configurable components creators. StoreManagerCreator CreateStoreMgr; @@ -53,29 +53,47 @@ class AnalysisManager : public BugReporterData { enum AnalysisScope { ScopeTU, ScopeDecl } AScope; - // The maximum number of exploded nodes the analyzer will generate. + /// \brief The maximum number of exploded nodes the analyzer will generate. unsigned MaxNodes; - // The maximum number of times the analyzer visit a block. + /// \brief The maximum number of times the analyzer visits a block. unsigned MaxVisit; bool VisualizeEGDot; bool VisualizeEGUbi; AnalysisPurgeMode PurgeDead; - /// EargerlyAssume - A flag indicating how the engine should handle - // expressions such as: 'x = (y != 0)'. When this flag is true then - // the subexpression 'y != 0' will be eagerly assumed to be true or false, - // thus evaluating it to the integers 0 or 1 respectively. The upside - // is that this can increase analysis precision until we have a better way - // to lazily evaluate such logic. The downside is that it eagerly - // bifurcates paths. + /// \brief The flag regulates if we should eagerly assume evaluations of + /// conditionals, thus, bifurcating the path. + /// + /// EagerlyAssume - A flag indicating how the engine should handle + /// expressions such as: 'x = (y != 0)'. When this flag is true then + /// the subexpression 'y != 0' will be eagerly assumed to be true or false, + /// thus evaluating it to the integers 0 or 1 respectively. The upside + /// is that this can increase analysis precision until we have a better way + /// to lazily evaluate such logic. The downside is that it eagerly + /// bifurcates paths. bool EagerlyAssume; bool TrimGraph; - bool InlineCall; bool EagerlyTrimEGraph; public: + // \brief inter-procedural analysis mode. + AnalysisIPAMode IPAMode; + + // Settings for inlining tuning. + /// \brief The inlining stack depth limit. + unsigned InlineMaxStackDepth; + /// \brief The max number of basic blocks in a function being inlined. + unsigned InlineMaxFunctionSize; + /// \brief The mode of function selection used during inlining. + AnalysisInliningMode InliningMode; + + /// \brief Do not re-analyze paths leading to exhausted nodes with a different + /// strategy. We get better code coverage when retry is enabled. + bool NoRetryExhausted; + +public: AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, const LangOptions &lang, PathDiagnosticConsumer *pd, StoreManagerCreator storemgr, @@ -85,9 +103,14 @@ public: unsigned maxnodes, unsigned maxvisit, bool vizdot, bool vizubi, AnalysisPurgeMode purge, bool eager, bool trim, - bool inlinecall, bool useUnoptimizedCFG, + bool useUnoptimizedCFG, bool addImplicitDtors, bool addInitializers, - bool eagerlyTrimEGraph); + bool eagerlyTrimEGraph, + AnalysisIPAMode ipa, + unsigned inlineMaxStack, + unsigned inlineMaxFunctionSize, + AnalysisInliningMode inliningMode, + bool NoRetry); /// Construct a clone of the given AnalysisManager with the given ASTContext /// and DiagnosticsEngine. @@ -97,11 +120,10 @@ public: ~AnalysisManager() { FlushDiagnostics(); } void ClearContexts() { - LocCtxMgr.clear(); AnaCtxMgr.clear(); } - AnalysisContextManager& getAnalysisContextManager() { + AnalysisDeclContextManager& getAnalysisDeclContextManager() { return AnaCtxMgr; } @@ -129,8 +151,8 @@ public: return Diags; } - const LangOptions &getLangOptions() const { - return LangInfo; + const LangOptions &getLangOpts() const { + return LangOpts; } virtual PathDiagnosticConsumer *getPathDiagnosticConsumer() { @@ -139,7 +161,7 @@ public: void FlushDiagnostics() { if (PD.get()) - PD->FlushDiagnostics(); + PD->FlushDiagnostics(0); } unsigned getMaxNodes() const { return MaxNodes; } @@ -162,11 +184,11 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } - bool shouldInlineCall() const { return InlineCall; } + bool shouldInlineCall() const { return (IPAMode == Inlining); } bool hasIndexer() const { return Idxer != 0; } - AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D); + AnalysisDeclContext *getAnalysisDeclContextInAnotherTU(const Decl *D); CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); @@ -181,38 +203,17 @@ public: return AnaCtxMgr.getContext(D)->getParentMap(); } - AnalysisContext *getAnalysisContext(const Decl *D) { + AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) { return AnaCtxMgr.getContext(D); } - AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) { + AnalysisDeclContext *getAnalysisDeclContext(const Decl *D, idx::TranslationUnit *TU) { return AnaCtxMgr.getContext(D, TU); } - const StackFrameContext *getStackFrame(AnalysisContext *Ctx, - LocationContext const *Parent, - const Stmt *S, - const CFGBlock *Blk, unsigned Idx) { - return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx); - } - - // Get the top level stack frame. - const StackFrameContext *getStackFrame(Decl const *D, - idx::TranslationUnit *TU) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0); - } - - // Get a stack frame with parent. - StackFrameContext const *getStackFrame(const Decl *D, - LocationContext const *Parent, - const Stmt *S, - const CFGBlock *Blk, unsigned Idx) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, - Blk,Idx); - } }; -} // end GR namespace +} // enAnaCtxMgrspace } // end clang namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 42a1537..9a699f9 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -18,17 +18,10 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" -#include "clang/AST/ASTContext.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/ImmutableList.h" namespace clang { - namespace ento { -class ProgramState; - class CompoundValData : public llvm::FoldingSetNode { QualType T; llvm::ImmutableList<SVal> L; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 1f14787..b051d33 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -15,48 +15,41 @@ #ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT -#include "clang/Analysis/Support/SaveAndRestore.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" namespace clang { - namespace ento { class CheckerContext { - ExplodedNodeSet &Dst; - StmtNodeBuilder &B; ExprEngine &Eng; + /// The current exploded(symbolic execution) graph node. ExplodedNode *Pred; - SaveAndRestore<bool> OldSink; - SaveOr OldHasGen; + /// The flag is true if the (state of the execution) has been modified + /// by the checker using this context. For example, a new transition has been + /// added or a bug report issued. + bool Changed; + /// The tagged location, which is used to generate all new nodes. const ProgramPoint Location; - const ProgramState *ST; - const unsigned size; -public: - bool *respondsToCallback; + NodeBuilder &NB; + public: - CheckerContext(ExplodedNodeSet &dst, - StmtNodeBuilder &builder, + /// If we are post visiting a call, this flag will be set if the + /// call was inlined. In all other cases it will be false. + const bool wasInlined; + + CheckerContext(NodeBuilder &builder, ExprEngine &eng, ExplodedNode *pred, const ProgramPoint &loc, - bool *respondsToCB = 0, - const ProgramState *st = 0) - : Dst(dst), - B(builder), - Eng(eng), + bool wasInlined = false) + : Eng(eng), Pred(pred), - OldSink(B.BuildSinks), - OldHasGen(B.hasGeneratedNode), + Changed(false), Location(loc), - ST(st), - size(Dst.size()), - respondsToCallback(respondsToCB) {} - - ~CheckerContext(); - - ExprEngine &getEngine() { - return Eng; + NB(builder), + wasInlined(wasInlined) { + assert(Pred->getState() && + "We should not call the checkers on an empty state."); } AnalysisManager &getAnalysisManager() { @@ -71,18 +64,34 @@ public: return Eng.getStoreManager(); } - ExplodedNodeSet &getNodeSet() { return Dst; } - ExplodedNode *&getPredecessor() { return Pred; } - const ProgramState *getState() { return ST ? ST : Pred->getState(); } + /// \brief Returns the previous node in the exploded graph, which includes + /// the state of the program before the checker ran. Note, checkers should + /// not retain the node in their state since the nodes might get invalidated. + ExplodedNode *getPredecessor() { return Pred; } + ProgramStateRef getState() const { return Pred->getState(); } + + /// \brief Check if the checker changed the state of the execution; ex: added + /// a new transition or a bug report. + bool isDifferent() { return Changed; } /// \brief Returns the number of times the current block has been visited /// along the analyzed path. - unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();} + unsigned getCurrentBlockCount() const { + return NB.getContext().getCurrentBlockCount(); + } ASTContext &getASTContext() { return Eng.getContext(); } - + + const LangOptions &getLangOpts() const { + return Eng.getContext().getLangOpts(); + } + + const LocationContext *getLocationContext() const { + return Pred->getLocationContext(); + } + BugReporter &getBugReporter() { return Eng.getBugReporter(); } @@ -99,83 +108,130 @@ public: return getSValBuilder().getSymbolManager(); } - bool isObjCGCEnabled() { + bool isObjCGCEnabled() const { return Eng.isObjCGCEnabled(); } - /// \brief Generate a default checker node (containing checker tag but no + ProgramStateManager &getStateManager() { + return Eng.getStateManager(); + } + + AnalysisDeclContext *getCurrentAnalysisDeclContext() const { + return Pred->getLocationContext()->getAnalysisDeclContext(); + } + + /// \brief If the given node corresponds to a PostStore program point, retrieve + /// the location region as it was uttered in the code. + /// + /// This utility can be useful for generating extensive diagnostics, for + /// example, for finding variables that the given symbol was assigned to. + static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { + ProgramPoint L = N->getLocation(); + if (const PostStore *PSL = dyn_cast<PostStore>(&L)) + return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); + return 0; + } + + /// \brief Generates a new transition in the program state graph + /// (ExplodedGraph). Uses the default CheckerContext predecessor node. + /// + /// @param State The state of the generated node. + /// @param Tag The tag is used to uniquely identify the creation site. If no + /// tag is specified, a default tag, unique to the given checker, + /// will be used. Tags are used to prevent states generated at + /// different sites from caching out. + ExplodedNode *addTransition(ProgramStateRef State, + const ProgramPointTag *Tag = 0) { + return addTransitionImpl(State, false, 0, Tag); + } + + /// \brief Generates a default transition (containing checker tag but no /// checker state changes). - ExplodedNode *generateNode(bool autoTransition = true) { - return generateNode(getState(), autoTransition); + ExplodedNode *addTransition() { + return addTransition(getState()); } - - /// \brief Generate a new checker node with the given predecessor. + + /// \brief Generates a new transition with the given predecessor. /// Allows checkers to generate a chain of nodes. - ExplodedNode *generateNode(const ProgramState *state, - ExplodedNode *pred, - const ProgramPointTag *tag = 0, - bool autoTransition = true) { - ExplodedNode *N = generateNodeImpl(state, false, pred, tag); - if (N && autoTransition) - addTransition(N); - return N; - } - - /// \brief Generate a new checker node. - ExplodedNode *generateNode(const ProgramState *state, - bool autoTransition = true, - const ProgramPointTag *tag = 0) { - ExplodedNode *N = generateNodeImpl(state, false, 0, tag); - if (N && autoTransition) - addTransition(N); - return N; + /// + /// @param State The state of the generated node. + /// @param Pred The transition will be generated from the specified Pred node + /// to the newly generated node. + /// @param Tag The tag to uniquely identify the creation site. + /// @param IsSink Mark the new node as sink, which will stop exploration of + /// the given path. + ExplodedNode *addTransition(ProgramStateRef State, + ExplodedNode *Pred, + const ProgramPointTag *Tag = 0, + bool IsSink = false) { + return addTransitionImpl(State, IsSink, Pred, Tag); } /// \brief Generate a sink node. Generating sink stops exploration of the /// given path. - ExplodedNode *generateSink(const ProgramState *state = 0) { - return generateNodeImpl(state ? state : getState(), true); - } - - void addTransition(ExplodedNode *node) { - Dst.Add(node); - } - - void addTransition(const ProgramState *state, - const ProgramPointTag *tag = 0) { - assert(state); - // If the 'state' is not new, we need to check if the cached state 'ST' - // is new. - if (state != getState() || (ST && ST != Pred->getState())) - // state is new or equals to ST. - generateNode(state, true, tag); - else - Dst.Add(Pred); + ExplodedNode *generateSink(ProgramStateRef state = 0) { + return addTransitionImpl(state ? state : getState(), true); } + /// \brief Emit the diagnostics report. void EmitReport(BugReport *R) { + Changed = true; Eng.getBugReporter().EmitReport(R); } - AnalysisContext *getCurrentAnalysisContext() const { - return Pred->getLocationContext()->getAnalysisContext(); + /// \brief Get the declaration of the called function (path-sensitive). + const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; + + /// \brief Get the name of the called function (path-sensitive). + StringRef getCalleeName(const FunctionDecl *FunDecl) const; + + /// \brief Get the name of the called function (path-sensitive). + StringRef getCalleeName(const CallExpr *CE) const { + const FunctionDecl *FunDecl = getCalleeDecl(CE); + return getCalleeName(FunDecl); } + /// Given a function declaration and a name checks if this is a C lib + /// function with the given name. + bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name); + static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name, + ASTContext &Context); + + /// \brief Depending on wither the location corresponds to a macro, return + /// either the macro name or the token spelling. + /// + /// This could be useful when checkers' logic depends on whether a function + /// is called with a given macro argument. For example: + /// s = socket(AF_INET,..) + /// If AF_INET is a macro, the result should be treated as a source of taint. + /// + /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName(). + StringRef getMacroNameOrSpelling(SourceLocation &Loc); + private: - ExplodedNode *generateNodeImpl(const ProgramState *state, - bool markAsSink, - ExplodedNode *pred = 0, - const ProgramPointTag *tag = 0) { - - ExplodedNode *node = B.generateNode(tag ? Location.withTag(tag) : Location, - state, - pred ? pred : Pred); - if (markAsSink && node) - node->markAsSink(); + ExplodedNode *addTransitionImpl(ProgramStateRef State, + bool MarkAsSink, + ExplodedNode *P = 0, + const ProgramPointTag *Tag = 0) { + if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) + return Pred; + + Changed = true; + ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location, + State, + P ? P : Pred, MarkAsSink); return node; } }; +/// \brief A helper class which wraps a boolean value set to false by default. +struct DefaultBool { + bool Val; + DefaultBool() : Val(false) {} + operator bool() const { return Val; } + DefaultBool &operator=(bool b) { Val = b; return *this; } +}; + } // end GR namespace } // end clang namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 3f6ddde..631858d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -22,44 +22,45 @@ class APSInt; } namespace clang { - namespace ento { -class ProgramState; -class ProgramStateManager; class SubEngine; class ConstraintManager { public: virtual ~ConstraintManager(); - virtual const ProgramState *assume(const ProgramState *state, + virtual ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption) = 0; - std::pair<const ProgramState*, const ProgramState*> - assumeDual(const ProgramState *state, DefinedSVal Cond) + std::pair<ProgramStateRef, ProgramStateRef > + assumeDual(ProgramStateRef state, DefinedSVal Cond) { - return std::make_pair(assume(state, Cond, true), - assume(state, Cond, false)); + std::pair<ProgramStateRef, ProgramStateRef > res = + std::make_pair(assume(state, Cond, true), assume(state, Cond, false)); + + assert(!(!res.first && !res.second) && "System is over constrained."); + return res; } - virtual const llvm::APSInt* getSymVal(const ProgramState *state, + virtual const llvm::APSInt* getSymVal(ProgramStateRef state, SymbolRef sym) const = 0; - virtual bool isEqual(const ProgramState *state, + virtual bool isEqual(ProgramStateRef state, SymbolRef sym, const llvm::APSInt& V) const = 0; - virtual const ProgramState *removeDeadBindings(const ProgramState *state, + virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) = 0; - virtual void print(const ProgramState *state, + virtual void print(ProgramStateRef state, raw_ostream &Out, const char* nl, const char *sep) = 0; - virtual void EndPath(const ProgramState *state) {} + virtual void EndPath(ProgramStateRef state) {} +protected: /// canReasonAbout - Not all ConstraintManagers can accurately reason about /// all SVal values. This method returns true if the ConstraintManager can /// reasonably handle a given SVal value. This is typically queried by diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 131d39e..59136fc 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -16,7 +16,9 @@ #define LLVM_CLANG_GR_COREENGINE #include "clang/AST/Expr.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "llvm/ADT/OwningPtr.h" @@ -27,6 +29,8 @@ class ProgramPointTag; namespace ento { +class NodeBuilder; + //===----------------------------------------------------------------------===// /// CoreEngine - Implements the core logic of the graph-reachability /// analysis. It traverses the CFG and generates the ExplodedGraph. @@ -37,15 +41,13 @@ namespace ento { /// at the statement and block-level. The analyses themselves must implement /// any transfer function logic and the sub-expression level (if any). class CoreEngine { - friend class StmtNodeBuilder; - friend class GenericNodeBuilderImpl; - friend class BranchNodeBuilder; + friend struct NodeBuilderContext; + friend class NodeBuilder; + friend class ExprEngine; + friend class CommonNodeBuilder; friend class IndirectGotoNodeBuilder; friend class SwitchNodeBuilder; friend class EndOfFunctionNodeBuilder; - friend class CallEnterNodeBuilder; - friend class CallExitNodeBuilder; - public: typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > BlocksExhausted; @@ -58,7 +60,7 @@ private: SubEngine& SubEng; /// G - The simulation graph. Each node is a (location,state) pair. - llvm::OwningPtr<ExplodedGraph> G; + OwningPtr<ExplodedGraph> G; /// WList - A set of queued nodes that need to be processed by the /// worklist algorithm. It is up to the implementation of WList to decide @@ -78,8 +80,16 @@ private: /// usually because it could not reason about something. BlocksAborted blocksAborted; + /// The functions which have been analyzed through inlining. This is owned by + /// AnalysisConsumer. It can be null. + SetOfConstDecls *AnalyzedCallees; + + /// The information about functions shared by the whole translation unit. + /// (This data is owned by AnalysisConsumer.) + FunctionSummariesTy *FunctionSummaries; + void generateNode(const ProgramPoint &Loc, - const ProgramState *State, + ProgramStateRef State, ExplodedNode *Pred); void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred); @@ -89,28 +99,23 @@ private: void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B, ExplodedNode *Pred); - void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, - unsigned Index, ExplodedNode *Pred); - void HandleCallExit(const CallExit &L, ExplodedNode *Pred); private: CoreEngine(const CoreEngine&); // Do not implement. CoreEngine& operator=(const CoreEngine&); + ExplodedNode *generateCallExitNode(ExplodedNode *N); + public: /// Construct a CoreEngine object to analyze the provided CFG using /// a DFS exploration of the exploded graph. - CoreEngine(SubEngine& subengine) + CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, + FunctionSummariesTy *FS) : SubEng(subengine), G(new ExplodedGraph()), WList(WorkList::makeBFS()), - BCounterFactory(G->getAllocator()) {} - - /// Construct a CoreEngine object to analyze the provided CFG and to - /// use the provided worklist object to execute the worklist algorithm. - /// The CoreEngine object assumes ownership of 'wlist'. - CoreEngine(WorkList* wlist, SubEngine& subengine) - : SubEng(subengine), G(new ExplodedGraph()), WList(wlist), - BCounterFactory(G->getAllocator()) {} + BCounterFactory(G->getAllocator()), + AnalyzedCallees(VisitedCallees), + FunctionSummaries(FS){} ~CoreEngine() { delete WList; @@ -126,12 +131,18 @@ public: /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps, - const ProgramState *InitState); - void ExecuteWorkListWithInitialState(const LocationContext *L, + ProgramStateRef InitState); + /// Returns true if there is still simulation state on the worklist. + bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, - const ProgramState *InitState, + ProgramStateRef InitState, ExplodedNodeSet &Dst); + /// Dispatch the work list item based on the given location information. + /// Use Pred parameter as the predecessor state. + void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, + const WorkListUnit& WU); + // Functions for external checking of whether we have unfinished work bool wasBlockAborted() const { return !blocksAborted.empty(); } bool wasBlocksExhausted() const { return !blocksExhausted.empty(); } @@ -159,160 +170,254 @@ public: BlocksAborted::const_iterator blocks_aborted_end() const { return blocksAborted.end(); } + + /// \brief Enqueue the given set of nodes onto the work list. + void enqueue(ExplodedNodeSet &Set); + + /// \brief Enqueue nodes that were created as a result of processing + /// a statement onto the work list. + void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx); + + /// \brief enqueue the nodes corresponding to the end of function onto the + /// end of path / work list. + void enqueueEndOfFunction(ExplodedNodeSet &Set); + + /// \brief Enqueue a single node created as a result of statement processing. + void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx); }; -class StmtNodeBuilder { - CoreEngine& Eng; - const CFGBlock &B; - const unsigned Idx; +// TODO: Turn into a calss. +struct NodeBuilderContext { + CoreEngine &Eng; + const CFGBlock *Block; ExplodedNode *Pred; + NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N) + : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); } + ExplodedNode *getPred() const { return Pred; } -public: - bool PurgingDeadSymbols; - bool BuildSinks; - bool hasGeneratedNode; - ProgramPoint::Kind PointKind; - const ProgramPointTag *Tag; + /// \brief Return the CFGBlock associated with this builder. + const CFGBlock *getBlock() const { return Block; } - typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy; - DeferredTy Deferred; + /// \brief Returns the number of times the current basic block has been + /// visited on the exploded graph path. + unsigned getCurrentBlockCount() const { + return Eng.WList->getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + Block->getBlockID()); + } +}; - void GenerateAutoTransition(ExplodedNode *N); +/// \class NodeBuilder +/// \brief This is the simplest builder which generates nodes in the +/// ExplodedGraph. +/// +/// The main benefit of the builder is that it automatically tracks the +/// frontier nodes (or destination set). This is the set of nodes which should +/// be propagated to the next step / builder. They are the nodes which have been +/// added to the builder (either as the input node set or as the newly +/// constructed nodes) but did not have any outgoing transitions added. +class NodeBuilder { + virtual void anchor(); +protected: + const NodeBuilderContext &C; + + /// Specifies if the builder results have been finalized. For example, if it + /// is set to false, autotransitions are yet to be generated. + bool Finalized; + bool HasGeneratedNodes; + /// \brief The frontier set - a set of nodes which need to be propagated after + /// the builder dies. + ExplodedNodeSet &Frontier; + + /// Checkes if the results are ready. + virtual bool checkResults() { + if (!Finalized) + return false; + return true; + } -public: - StmtNodeBuilder(const CFGBlock *b, - unsigned idx, - ExplodedNode *N, - CoreEngine* e); + bool hasNoSinksInFrontier() { + for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) { + if ((*I)->isSink()) + return false; + } + return true; + } - ~StmtNodeBuilder(); + /// Allow subclasses to finalize results before result_begin() is executed. + virtual void finalizeResults() {} + + ExplodedNode *generateNodeImpl(const ProgramPoint &PP, + ProgramStateRef State, + ExplodedNode *Pred, + bool MarkAsSink = false); - ExplodedNode *getPredecessor() const { return Pred; } +public: + NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, bool F = true) + : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { + Frontier.Add(SrcNode); + } - // FIXME: This should not be exposed. - WorkList *getWorkList() { return Eng.WList; } + NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, bool F = true) + : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { + Frontier.insert(SrcSet); + assert(hasNoSinksInFrontier()); + } - BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + virtual ~NodeBuilder() {} - unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited( - Pred->getLocationContext()->getCurrentStackFrame(), - B.getBlockID()); + /// \brief Generates a node in the ExplodedGraph. + /// + /// When a node is marked as sink, the exploration from the node is stopped - + /// the node becomes the last node on the path. + ExplodedNode *generateNode(const ProgramPoint &PP, + ProgramStateRef State, + ExplodedNode *Pred, + bool MarkAsSink = false) { + return generateNodeImpl(PP, State, Pred, MarkAsSink); } - ExplodedNode *generateNode(const Stmt *S, - const ProgramState *St, - ExplodedNode *Pred, - ProgramPoint::Kind K, - const ProgramPointTag *tag = 0) { - hasGeneratedNode = true; + const ExplodedNodeSet &getResults() { + finalizeResults(); + assert(checkResults()); + return Frontier; + } + + typedef ExplodedNodeSet::iterator iterator; + /// \brief Iterators through the results frontier. + inline iterator begin() { + finalizeResults(); + assert(checkResults()); + return Frontier.begin(); + } + inline iterator end() { + finalizeResults(); + return Frontier.end(); + } - if (PurgingDeadSymbols) - K = ProgramPoint::PostPurgeDeadSymbolsKind; + const NodeBuilderContext &getContext() { return C; } + bool hasGeneratedNodes() { return HasGeneratedNodes; } - return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag); + void takeNodes(const ExplodedNodeSet &S) { + for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I ) + Frontier.erase(*I); } + void takeNodes(ExplodedNode *N) { Frontier.erase(N); } + void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); } + void addNodes(ExplodedNode *N) { Frontier.Add(N); } +}; - ExplodedNode *generateNode(const Stmt *S, - const ProgramState *St, +/// \class NodeBuilderWithSinks +/// \brief This node builder keeps track of the generated sink nodes. +class NodeBuilderWithSinks: public NodeBuilder { + virtual void anchor(); +protected: + SmallVector<ExplodedNode*, 2> sinksGenerated; + ProgramPoint &Location; + +public: + NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, ProgramPoint &L) + : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} + ExplodedNode *generateNode(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *tag = 0) { - return generateNode(S, St, Pred, PointKind, tag); - } + const ProgramPointTag *Tag = 0, + bool MarkAsSink = false) { + ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location); - ExplodedNode *generateNode(const ProgramPoint &PP, - const ProgramState *State, - ExplodedNode *Pred) { - hasGeneratedNode = true; - return generateNodeInternal(PP, State, Pred); + ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink); + if (N && N->isSink()) + sinksGenerated.push_back(N); + return N; } - ExplodedNode* - generateNodeInternal(const ProgramPoint &PP, - const ProgramState *State, - ExplodedNode *Pred); - - ExplodedNode* - generateNodeInternal(const Stmt *S, - const ProgramState *State, - ExplodedNode *Pred, - ProgramPoint::Kind K, - const ProgramPointTag *tag = 0); - - /// getStmt - Return the current block-level expression associated with - /// this builder. - const Stmt *getStmt() const { - const CFGStmt *CS = B[Idx].getAs<CFGStmt>(); - return CS ? CS->getStmt() : 0; + const SmallVectorImpl<ExplodedNode*> &getSinks() const { + return sinksGenerated; } +}; - /// getBlock - Return the CFGBlock associated with the block-level expression - /// of this builder. - const CFGBlock *getBlock() const { return &B; } +/// \class StmtNodeBuilder +/// \brief This builder class is useful for generating nodes that resulted from +/// visiting a statement. The main difference from it's parent NodeBuilder is +/// that it creates a statement specific ProgramPoint. +class StmtNodeBuilder: public NodeBuilder { + NodeBuilder *EnclosingBldr; +public: - unsigned getIndex() const { return Idx; } + /// \brief Constructs a StmtNodeBuilder. If the builder is going to process + /// nodes currently owned by another builder(with larger scope), use + /// Enclosing builder to transfer ownership. + StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) + : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) { + if (EnclosingBldr) + EnclosingBldr->takeNodes(SrcNode); + } - ExplodedNode *MakeNode(ExplodedNodeSet &Dst, - const Stmt *S, - ExplodedNode *Pred, - const ProgramState *St) { - return MakeNode(Dst, S, Pred, St, PointKind); + StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) + : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { + if (EnclosingBldr) + for (ExplodedNodeSet::iterator I = SrcSet.begin(), + E = SrcSet.end(); I != E; ++I ) + EnclosingBldr->takeNodes(*I); } - ExplodedNode *MakeNode(ExplodedNodeSet &Dst, - const Stmt *S, - ExplodedNode *Pred, - const ProgramState *St, - ProgramPoint::Kind K); + virtual ~StmtNodeBuilder(); - ExplodedNode *MakeSinkNode(ExplodedNodeSet &Dst, - const Stmt *S, + ExplodedNode *generateNode(const Stmt *S, ExplodedNode *Pred, - const ProgramState *St) { - bool Tmp = BuildSinks; - BuildSinks = true; - ExplodedNode *N = MakeNode(Dst, S, Pred, St); - BuildSinks = Tmp; - return N; + ProgramStateRef St, + bool MarkAsSink = false, + const ProgramPointTag *tag = 0, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ + const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, + Pred->getLocationContext(), tag); + return generateNodeImpl(L, St, Pred, MarkAsSink); + } + + ExplodedNode *generateNode(const ProgramPoint &PP, + ExplodedNode *Pred, + ProgramStateRef State, + bool MarkAsSink = false) { + return generateNodeImpl(PP, State, Pred, MarkAsSink); } }; -class BranchNodeBuilder { - CoreEngine& Eng; - const CFGBlock *Src; +/// \brief BranchNodeBuilder is responsible for constructing the nodes +/// corresponding to the two branches of the if statement - true and false. +class BranchNodeBuilder: public NodeBuilder { + virtual void anchor(); const CFGBlock *DstT; const CFGBlock *DstF; - ExplodedNode *Pred; - typedef SmallVector<ExplodedNode*,3> DeferredTy; - DeferredTy Deferred; - - bool GeneratedTrue; - bool GeneratedFalse; bool InFeasibleTrue; bool InFeasibleFalse; public: - BranchNodeBuilder(const CFGBlock *src, const CFGBlock *dstT, - const CFGBlock *dstF, ExplodedNode *pred, CoreEngine* e) - : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), - GeneratedTrue(false), GeneratedFalse(false), - InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} - - ~BranchNodeBuilder(); - - ExplodedNode *getPredecessor() const { return Pred; } - - const ExplodedGraph& getGraph() const { return *Eng.G; } - - BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, + const NodeBuilderContext &C, + const CFGBlock *dstT, const CFGBlock *dstF) + : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { + // The branch node builder does not generate autotransitions. + // If there are no successors it means that both branches are infeasible. + takeNodes(SrcNode); + } - /// This function generates a new ExplodedNode but not a new - /// branch(block edge). - ExplodedNode *generateNode(const Stmt *Condition, const ProgramState *State); + BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, + const NodeBuilderContext &C, + const CFGBlock *dstT, const CFGBlock *dstF) + : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { + takeNodes(SrcSet); + } - ExplodedNode *generateNode(const ProgramState *State, bool branch); + ExplodedNode *generateNode(ProgramStateRef State, bool branch, + ExplodedNode *Pred); const CFGBlock *getTargetBlock(bool branch) const { return branch ? DstT : DstF; @@ -320,18 +425,14 @@ public: void markInfeasible(bool branch) { if (branch) - InFeasibleTrue = GeneratedTrue = true; + InFeasibleTrue = true; else - InFeasibleFalse = GeneratedFalse = true; + InFeasibleFalse = true; } bool isFeasible(bool branch) { return branch ? !InFeasibleTrue : !InFeasibleFalse; } - - const ProgramState *getState() const { - return getPredecessor()->getState(); - } }; class IndirectGotoNodeBuilder { @@ -369,12 +470,16 @@ public: iterator end() { return iterator(DispatchBlock.succ_end()); } ExplodedNode *generateNode(const iterator &I, - const ProgramState *State, + ProgramStateRef State, bool isSink = false); const Expr *getTarget() const { return E; } - const ProgramState *getState() const { return Pred->State; } + ProgramStateRef getState() const { return Pred->State; } + + const LocationContext *getLocationContext() const { + return Pred->getLocationContext(); + } }; class SwitchNodeBuilder { @@ -416,167 +521,21 @@ public: } ExplodedNode *generateCaseStmtNode(const iterator &I, - const ProgramState *State); + ProgramStateRef State); - ExplodedNode *generateDefaultCaseNode(const ProgramState *State, + ExplodedNode *generateDefaultCaseNode(ProgramStateRef State, bool isSink = false); const Expr *getCondition() const { return Condition; } - const ProgramState *getState() const { return Pred->State; } -}; - -class GenericNodeBuilderImpl { -protected: - CoreEngine &engine; - ExplodedNode *pred; - ProgramPoint pp; - SmallVector<ExplodedNode*, 2> sinksGenerated; - - ExplodedNode *generateNodeImpl(const ProgramState *state, - ExplodedNode *pred, - ProgramPoint programPoint, - bool asSink); - - GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p) - : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {} - -public: - bool hasGeneratedNode; - - WorkList &getWorkList() { return *engine.WList; } - - ExplodedNode *getPredecessor() const { return pred; } + ProgramStateRef getState() const { return Pred->State; } - BlockCounter getBlockCounter() const { - return engine.WList->getBlockCounter(); - } - - const SmallVectorImpl<ExplodedNode*> &sinks() const { - return sinksGenerated; - } -}; - -template <typename PP_T> -class GenericNodeBuilder : public GenericNodeBuilderImpl { -public: - GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p) - : GenericNodeBuilderImpl(eng, pr, p) {} - - ExplodedNode *generateNode(const ProgramState *state, ExplodedNode *pred, - const ProgramPointTag *tag, bool asSink) { - return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag), - asSink); - } - - const PP_T &getProgramPoint() const { return cast<PP_T>(pp); } -}; - -class EndOfFunctionNodeBuilder { - CoreEngine &Eng; - const CFGBlock &B; - ExplodedNode *Pred; - const ProgramPointTag *Tag; - -public: - bool hasGeneratedNode; - -public: - EndOfFunctionNodeBuilder(const CFGBlock *b, ExplodedNode *N, CoreEngine* e, - const ProgramPointTag *tag = 0) - : Eng(*e), B(*b), Pred(N), Tag(tag), hasGeneratedNode(false) {} - - ~EndOfFunctionNodeBuilder(); - - EndOfFunctionNodeBuilder withCheckerTag(const ProgramPointTag *tag) { - return EndOfFunctionNodeBuilder(&B, Pred, &Eng, tag); - } - - WorkList &getWorkList() { return *Eng.WList; } - - ExplodedNode *getPredecessor() const { return Pred; } - - BlockCounter getBlockCounter() const { - return Eng.WList->getBlockCounter(); - } - - unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited( - Pred->getLocationContext()->getCurrentStackFrame(), - B.getBlockID()); - } - - ExplodedNode *generateNode(const ProgramState *State, - ExplodedNode *P = 0, - const ProgramPointTag *tag = 0); - - void GenerateCallExitNode(const ProgramState *state); - - const CFGBlock *getBlock() const { return &B; } - - const ProgramState *getState() const { - return getPredecessor()->getState(); - } -}; - -class CallEnterNodeBuilder { - CoreEngine &Eng; - - const ExplodedNode *Pred; - - // The call site. For implicit automatic object dtor, this is the trigger - // statement. - const Stmt *CE; - - // The context of the callee. - const StackFrameContext *CalleeCtx; - - // The parent block of the CallExpr. - const CFGBlock *Block; - - // The CFGBlock index of the CallExpr. - unsigned Index; - -public: - CallEnterNodeBuilder(CoreEngine &eng, const ExplodedNode *pred, - const Stmt *s, const StackFrameContext *callee, - const CFGBlock *blk, unsigned idx) - : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {} - - const ProgramState *getState() const { return Pred->getState(); } - - const LocationContext *getLocationContext() const { + const LocationContext *getLocationContext() const { return Pred->getLocationContext(); } - - const Stmt *getCallExpr() const { return CE; } - - const StackFrameContext *getCalleeContext() const { return CalleeCtx; } - - const CFGBlock *getBlock() const { return Block; } - - unsigned getIndex() const { return Index; } - - void generateNode(const ProgramState *state); }; -class CallExitNodeBuilder { - CoreEngine &Eng; - const ExplodedNode *Pred; - -public: - CallExitNodeBuilder(CoreEngine &eng, const ExplodedNode *pred) - : Eng(eng), Pred(pred) {} - - const ExplodedNode *getPredecessor() const { return Pred; } - - const ProgramState *getState() const { return Pred->getState(); } - - void generateNode(const ProgramState *state); -}; - -} // end GR namespace - +} // end ento namespace } // end clang namespace #endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index 2463e23..b80213e 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_GR_ENVIRONMENT_H #define LLVM_CLANG_GR_ENVIRONMENT_H +#include "clang/Analysis/AnalysisContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/ImmutableMap.h" @@ -26,15 +27,39 @@ namespace ento { class EnvironmentManager; class SValBuilder; -/// Environment - An immutable map from Stmts to their current -/// symbolic values (SVals). -/// +/// An entry in the environment consists of a Stmt and an LocationContext. +/// This allows the environment to manage context-sensitive bindings, +/// which is essentially for modeling recursive function analysis, among +/// other things. +class EnvironmentEntry : public std::pair<const Stmt*, + const StackFrameContext *> { +public: + EnvironmentEntry(const Stmt *s, const LocationContext *L) + : std::pair<const Stmt*, + const StackFrameContext*>(s, L ? L->getCurrentStackFrame():0) {} + + const Stmt *getStmt() const { return first; } + const LocationContext *getLocationContext() const { return second; } + + /// Profile an EnvironmentEntry for inclusion in a FoldingSet. + static void Profile(llvm::FoldingSetNodeID &ID, + const EnvironmentEntry &E) { + ID.AddPointer(E.getStmt()); + ID.AddPointer(E.getLocationContext()); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, *this); + } +}; + +/// An immutable map from EnvironemntEntries to SVals. class Environment { private: friend class EnvironmentManager; // Type definitions. - typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy; + typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy; // Data. BindingsTy ExprBindings; @@ -42,18 +67,18 @@ private: Environment(BindingsTy eb) : ExprBindings(eb) {} - SVal lookupExpr(const Stmt *E) const; + SVal lookupExpr(const EnvironmentEntry &E) const; public: typedef BindingsTy::iterator iterator; iterator begin() const { return ExprBindings.begin(); } iterator end() const { return ExprBindings.end(); } - - /// getSVal - Fetches the current binding of the expression in the - /// Environment. - SVal getSVal(const Stmt *Ex, SValBuilder& svalBuilder, - bool useOnlyDirectBindings = false) const; + /// Fetches the current binding of the expression in the + /// Environment. + SVal getSVal(const EnvironmentEntry &E, + SValBuilder &svalBuilder, + bool useOnlyDirectBindings = false) const; /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. @@ -70,6 +95,12 @@ public: bool operator==(const Environment& RHS) const { return ExprBindings == RHS.ExprBindings; } + + void print(raw_ostream &Out, const char *NL, const char *Sep) const; + +private: + void printAux(raw_ostream &Out, bool printLocations, + const char *NL, const char *Sep) const; }; class EnvironmentManager { @@ -85,17 +116,20 @@ public: return Environment(F.getEmptyMap()); } - /// Bind the value 'V' to the statement 'S'. - Environment bindExpr(Environment Env, const Stmt *S, SVal V, + /// Bind a symbolic value to the given environment entry. + Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V, bool Invalidate); - /// Bind the location 'location' and value 'V' to the statement 'S'. This - /// is used when simulating loads/stores. - Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location, + /// Bind the location 'location' and value 'V' to the specified + /// environment entry. + Environment bindExprAndLocation(Environment Env, + const EnvironmentEntry &E, + SVal location, SVal V); Environment removeDeadBindings(Environment Env, - SymbolReaper &SymReaper, const ProgramState *ST); + SymbolReaper &SymReaper, + ProgramStateRef state); }; } // end GR namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index fdfed3d..46fbb88 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -32,6 +32,7 @@ #include "llvm/Support/Casting.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include <vector> namespace clang { @@ -53,7 +54,7 @@ class ExplodedGraph; class ExplodedNode : public llvm::FoldingSetNode { friend class ExplodedGraph; friend class CoreEngine; - friend class StmtNodeBuilder; + friend class NodeBuilder; friend class BranchNodeBuilder; friend class IndirectGotoNodeBuilder; friend class SwitchNodeBuilder; @@ -106,7 +107,7 @@ class ExplodedNode : public llvm::FoldingSetNode { const ProgramPoint Location; /// State - The state associated with this node. - const ProgramState *State; + ProgramStateRef State; /// Preds - The predecessors of this node. NodeGroup Preds; @@ -116,14 +117,14 @@ class ExplodedNode : public llvm::FoldingSetNode { public: - explicit ExplodedNode(const ProgramPoint &loc, const ProgramState *state) + explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, + bool IsSink) : Location(loc), State(state) { - const_cast<ProgramState*>(State)->incrementReferenceCount(); + if (IsSink) + Succs.setFlag(); } - ~ExplodedNode() { - const_cast<ProgramState*>(State)->decrementReferenceCount(); - } + ~ExplodedNode() {} /// getLocation - Returns the edge associated with the given node. ProgramPoint getLocation() const { return Location; } @@ -143,19 +144,22 @@ public: return *getLocationContext()->getAnalysis<T>(); } - const ProgramState *getState() const { return State; } + ProgramStateRef getState() const { return State; } template <typename T> const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); } static void Profile(llvm::FoldingSetNodeID &ID, - const ProgramPoint &Loc, const ProgramState *state) { + const ProgramPoint &Loc, + ProgramStateRef state, + bool IsSink) { ID.Add(Loc); - ID.AddPointer(state); + ID.AddPointer(state.getPtr()); + ID.AddBoolean(IsSink); } void Profile(llvm::FoldingSetNodeID& ID) const { - Profile(ID, getLocation(), getState()); + Profile(ID, getLocation(), getState(), isSink()); } /// addPredeccessor - Adds a predecessor to the current node, and @@ -168,7 +172,10 @@ public: bool pred_empty() const { return Preds.empty(); } bool isSink() const { return Succs.getFlag(); } - void markAsSink() { Succs.setFlag(); } + + bool hasSinglePred() const { + return (pred_size() == 1); + } ExplodedNode *getFirstPred() { return pred_empty() ? NULL : *(pred_begin()); @@ -223,6 +230,7 @@ private: // FIXME: Is this class necessary? class InterExplodedGraphMap { + virtual void anchor(); llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M; friend class ExplodedGraph; @@ -238,18 +246,17 @@ protected: friend class CoreEngine; // Type definitions. - typedef SmallVector<ExplodedNode*,2> RootsTy; - typedef SmallVector<ExplodedNode*,10> EndNodesTy; + typedef std::vector<ExplodedNode *> NodeVector; - /// Roots - The roots of the simulation graph. Usually there will be only + /// The roots of the simulation graph. Usually there will be only /// one, but clients are free to establish multiple subgraphs within a single /// SimulGraph. Moreover, these subgraphs can often merge when paths from /// different roots reach the same state at the same program location. - RootsTy Roots; + NodeVector Roots; - /// EndNodes - The nodes in the simulation graph which have been - /// specially marked as the endpoint of an abstract simulation path. - EndNodesTy EndNodes; + /// The nodes in the simulation graph which have been + /// specially marked as the endpoint of an abstract simulation path. + NodeVector EndNodes; /// Nodes - The nodes in the graph. llvm::FoldingSet<ExplodedNode> Nodes; @@ -262,21 +269,25 @@ protected: unsigned NumNodes; /// A list of recently allocated nodes that can potentially be recycled. - void *recentlyAllocatedNodes; + NodeVector ChangedNodes; /// A list of nodes that can be reused. - void *freeNodes; + NodeVector FreeNodes; /// A flag that indicates whether nodes should be recycled. bool reclaimNodes; + + /// Counter to determine when to reclaim nodes. + unsigned reclaimCounter; public: - /// getNode - Retrieve the node associated with a (Location,State) pair, + + /// \brief Retrieve the node associated with a (Location,State) pair, /// where the 'Location' is a ProgramPoint in the CFG. If no node for - /// this pair exists, it is created. IsNew is set to true if + /// this pair exists, it is created. IsNew is set to true if /// the node was freshly created. - - ExplodedNode *getNode(const ProgramPoint &L, const ProgramState *State, + ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State, + bool IsSink = false, bool* IsNew = 0); ExplodedGraph* MakeEmptyGraph() const { @@ -295,9 +306,7 @@ public: return V; } - ExplodedGraph() - : NumNodes(0), recentlyAllocatedNodes(0), - freeNodes(0), reclaimNodes(false) {} + ExplodedGraph(); ~ExplodedGraph(); @@ -310,10 +319,10 @@ public: // Iterators. typedef ExplodedNode NodeTy; typedef llvm::FoldingSet<ExplodedNode> AllNodesTy; - typedef NodeTy** roots_iterator; - typedef NodeTy* const * const_roots_iterator; - typedef NodeTy** eop_iterator; - typedef NodeTy* const * const_eop_iterator; + typedef NodeVector::iterator roots_iterator; + typedef NodeVector::const_iterator const_roots_iterator; + typedef NodeVector::iterator eop_iterator; + typedef NodeVector::const_iterator const_eop_iterator; typedef AllNodesTy::iterator node_iterator; typedef AllNodesTy::const_iterator const_node_iterator; @@ -362,6 +371,10 @@ public: /// Reclaim "uninteresting" nodes created since the last time this method /// was called. void reclaimRecentlyAllocatedNodes(); + +private: + bool shouldCollect(const ExplodedNode *node); + void collectNode(ExplodedNode *node); }; class ExplodedNodeSet { @@ -380,19 +393,16 @@ public: if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N); } - ExplodedNodeSet &operator=(const ExplodedNodeSet &X) { - Impl = X.Impl; - return *this; - } - typedef ImplTy::iterator iterator; typedef ImplTy::const_iterator const_iterator; unsigned size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } + bool erase(ExplodedNode *N) { return Impl.erase(N); } void clear() { Impl.clear(); } void insert(const ExplodedNodeSet &S) { + assert(&S != this); if (empty()) Impl = S.Impl; else diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 9bc470f..2a21a03 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -20,16 +20,24 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtObjC.h" namespace clang { +class AnalysisDeclContextManager; +class CXXCatchStmt; +class CXXConstructExpr; +class CXXDeleteExpr; +class CXXNewExpr; +class CXXTemporaryObjectExpr; +class CXXThisExpr; +class MaterializeTemporaryExpr; +class ObjCAtSynchronizedStmt; class ObjCForCollectionStmt; - + namespace ento { class AnalysisManager; @@ -38,16 +46,14 @@ class ObjCMessage; class ExprEngine : public SubEngine { AnalysisManager &AMgr; + + AnalysisDeclContextManager &AnalysisDeclContexts; CoreEngine Engine; /// G - the simulation graph. ExplodedGraph& G; - /// Builder - The current StmtNodeBuilder which is used when building the - /// nodes for a given statement. - StmtNodeBuilder* Builder; - /// StateMgr - Object that manages the data for all created states. ProgramStateManager StateMgr; @@ -62,10 +68,12 @@ class ExprEngine : public SubEngine { /// CleanedState - The state for EntryNode "cleaned" of all dead /// variables and symbols (as determined by a liveness analysis). - const ProgramState *CleanedState; + ProgramStateRef CleanedState; /// currentStmt - The current block-level statement. const Stmt *currentStmt; + unsigned int currentStmtIdx; + const NodeBuilderContext *currentBuilderContext; /// Obj-C Class Identifiers. IdentifierInfo* NSExceptionII; @@ -83,21 +91,25 @@ class ExprEngine : public SubEngine { GRBugReporter BR; public: - ExprEngine(AnalysisManager &mgr, bool gcEnabled); + ExprEngine(AnalysisManager &mgr, bool gcEnabled, + SetOfConstDecls *VisitedCallees, + FunctionSummariesTy *FS); ~ExprEngine(); - void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { - Engine.ExecuteWorkList(L, Steps, 0); + /// Returns true if there is still simulation state on the worklist. + bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { + return Engine.ExecuteWorkList(L, Steps, 0); } /// Execute the work list with an initial state. Nodes that reaches the exit /// of the function are added into the Dst set, which represent the exit - /// state of the function call. - void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, - const ProgramState *InitState, + /// state of the function call. Returns true if there is still simulation + /// state on the worklist. + bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, + ProgramStateRef InitState, ExplodedNodeSet &Dst) { - Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); + return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); } /// getContext - Return the ASTContext associated with this analysis. @@ -113,10 +125,19 @@ public: BugReporter& getBugReporter() { return BR; } - StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } + const NodeBuilderContext &getBuilderContext() { + assert(currentBuilderContext); + return *currentBuilderContext; + } bool isObjCGCEnabled() { return ObjCGCEnabled; } + const Stmt *getStmt() const; + + void GenerateAutoTransition(ExplodedNode *N); + void enqueueEndOfPath(ExplodedNodeSet &S); + void GenerateCallExitNode(ExplodedNode *N); + /// ViewGraph - Visualize the ExplodedGraph created by executing the /// simulation. void ViewGraph(bool trim = false); @@ -125,36 +146,43 @@ public: /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. - const ProgramState *getInitialState(const LocationContext *InitLoc); + ProgramStateRef getInitialState(const LocationContext *InitLoc); ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } /// processCFGElement - Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a CFG element. - void processCFGElement(const CFGElement E, StmtNodeBuilder& builder); + void processCFGElement(const CFGElement E, ExplodedNode *Pred, + unsigned StmtIdx, NodeBuilderContext *Ctx); - void ProcessStmt(const CFGStmt S, StmtNodeBuilder &builder); + void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); - void ProcessInitializer(const CFGInitializer I, StmtNodeBuilder &builder); + void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred); - void ProcessImplicitDtor(const CFGImplicitDtor D, StmtNodeBuilder &builder); + void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, - StmtNodeBuilder &builder); - void ProcessBaseDtor(const CFGBaseDtor D, StmtNodeBuilder &builder); - void ProcessMemberDtor(const CFGMemberDtor D, StmtNodeBuilder &builder); + ExplodedNode *Pred, ExplodedNodeSet &Dst); + void ProcessBaseDtor(const CFGBaseDtor D, + ExplodedNode *Pred, ExplodedNodeSet &Dst); + void ProcessMemberDtor(const CFGMemberDtor D, + ExplodedNode *Pred, ExplodedNodeSet &Dst); void ProcessTemporaryDtor(const CFGTemporaryDtor D, - StmtNodeBuilder &builder); + ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Called by CoreEngine when processing the entrance of a CFGBlock. - virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes, - GenericNodeBuilder<BlockEntrance> &nodeBuilder); + virtual void processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder); /// ProcessBranch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. void processBranch(const Stmt *Condition, const Stmt *Term, - BranchNodeBuilder& builder); + NodeBuilderContext& BuilderCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF); /// processIndirectGoto - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. @@ -166,35 +194,36 @@ public: /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - void processEndOfFunction(EndOfFunctionNodeBuilder& builder); + void processEndOfFunction(NodeBuilderContext& BC); /// Generate the entry node of the callee. - void processCallEnter(CallEnterNodeBuilder &builder); + void processCallEnter(CallEnter CE, ExplodedNode *Pred); /// Generate the first post callsite node. - void processCallExit(CallExitNodeBuilder &builder); + void processCallExit(ExplodedNode *Pred); /// Called by CoreEngine when the analysis worklist has terminated. void processEndWorklist(bool hasWorkRemaining); /// evalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. - const ProgramState *processAssume(const ProgramState *state, SVal cond,bool assumption); + ProgramStateRef processAssume(ProgramStateRef state, SVal cond,bool assumption); /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a /// region change should trigger a processRegionChanges update. - bool wantsRegionChangeUpdate(const ProgramState *state); + bool wantsRegionChangeUpdate(ProgramStateRef state); /// processRegionChanges - Called by ProgramStateManager whenever a change is made /// to the store. Used to update checkers that track region values. - const ProgramState * - processRegionChanges(const ProgramState *state, + ProgramStateRef + processRegionChanges(ProgramStateRef state, const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions); + ArrayRef<const MemRegion *> Regions, + const CallOrObjCMessage *Call); /// printState - Called by ProgramStateManager to print checker-specific data. - void printState(raw_ostream &Out, const ProgramState *State, + void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep); virtual ProgramStateManager& getStateManager() { return StateMgr; } @@ -225,11 +254,6 @@ public: const CoreEngine &getCoreEngine() const { return Engine; } public: - ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S, - ExplodedNode *Pred, const ProgramState *St, - ProgramPoint::Kind K = ProgramPoint::PostStmtKind, - const ProgramPointTag *tag = 0); - /// Visit - Transfer function logic for all statements. Dispatches to /// other functions that handle specific kinds of statements. void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -241,16 +265,6 @@ public: /// VisitAsmStmt - Transfer function logic for inline asm. void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); - - void VisitAsmStmtHelperOutputs(const AsmStmt *A, - AsmStmt::const_outputs_iterator I, - AsmStmt::const_outputs_iterator E, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - - void VisitAsmStmtHelperInputs(const AsmStmt *A, - AsmStmt::const_inputs_iterator I, - AsmStmt::const_inputs_iterator E, - ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitBlockExpr - Transfer function logic for BlockExprs. void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, @@ -328,13 +342,19 @@ public: void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, ExplodedNodeSet &Dst); + /// Handle ++ and -- (both pre- and post-increment). + void VisitIncrementDecrementOperator(const UnaryOperator* U, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst); void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, - ExplodedNode *Pred, ExplodedNodeSet &Dst) { - VisitCXXConstructExpr(expr, 0, Pred, Dst); - } + ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -349,9 +369,6 @@ public: void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitAggExpr(const Expr *E, const MemRegion *Dest, ExplodedNode *Pred, - ExplodedNodeSet &Dst); - /// Create a C++ temporary object for an rvalue. void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, @@ -363,17 +380,7 @@ public: const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl, const StackFrameContext *frameCtx); - - /// Evaluate arguments with a work list algorithm. - void evalArguments(ConstExprIterator AI, ConstExprIterator AE, - const FunctionProtoType *FnType, - ExplodedNode *Pred, ExplodedNodeSet &Dst, - bool FstArgAsLValue = false); - /// Evaluate callee expression (for a function call). - void evalCallee(const CallExpr *callExpr, const ExplodedNodeSet &src, - ExplodedNodeSet &dest); - /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. @@ -393,31 +400,34 @@ public: public: - SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op, + SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc L, NonLoc R, QualType T) { return svalBuilder.evalBinOpNN(state, op, L, R, T); } - SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op, + SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; } - SVal evalBinOp(const ProgramState *ST, BinaryOperator::Opcode Op, + SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T) { return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); } protected: - void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg, - ExplodedNode *Pred, const ProgramState *state); + void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg, + ExplodedNode *Pred, ProgramStateRef state, + bool GenSink); - const ProgramState *invalidateArguments(const ProgramState *State, + ProgramStateRef invalidateArguments(ProgramStateRef State, const CallOrObjCMessage &Call, const LocationContext *LC); - const ProgramState *MarkBranch(const ProgramState *St, const Stmt *Terminator, - bool branchTaken); + ProgramStateRef MarkBranch(ProgramStateRef state, + const Stmt *Terminator, + const LocationContext *LCtx, + bool branchTaken); /// evalBind - Handle the semantics of binding a value to a specific location. /// This method is used by evalStore, VisitDeclStmt, and others. @@ -431,34 +441,52 @@ public: // be the same as Pred->state, and when 'location' may not be the // same as state->getLValue(Ex). /// Simulate a read of the result of Ex. - void evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred, - const ProgramState *St, SVal location, const ProgramPointTag *tag = 0, + void evalLoad(ExplodedNodeSet &Dst, + const Expr *NodeEx, /* Eventually will be a CFGStmt */ + const Expr *BoundExpr, + ExplodedNode *Pred, + ProgramStateRef St, + SVal location, + const ProgramPointTag *tag = 0, QualType LoadTy = QualType()); // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, - ExplodedNode *Pred, const ProgramState *St, SVal TargetLV, SVal Val, + ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag = 0); private: - void evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred, - const ProgramState *St, SVal location, const ProgramPointTag *tag, + void evalLoadCommon(ExplodedNodeSet &Dst, + const Expr *NodeEx, /* Eventually will be a CFGStmt */ + const Expr *BoundEx, + ExplodedNode *Pred, + ProgramStateRef St, + SVal location, + const ProgramPointTag *tag, QualType LoadTy); // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *Pred, - const ProgramState *St, SVal location, + void evalLocation(ExplodedNodeSet &Dst, + const Stmt *NodeEx, /* This will eventually be a CFGStmt */ + const Stmt *BoundEx, + ExplodedNode *Pred, + ProgramStateRef St, SVal location, const ProgramPointTag *tag, bool isLoad); + bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred); bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); - - -public: - /// Returns true if calling the specific function or method would possibly - /// cause global variables to be invalidated. - bool doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const; - + + bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); +}; + +/// Traits for storing the call processing policy inside GDM. +/// The GDM stores the corresponding CallExpr pointer. +struct ReplayWithoutInlining{}; +template <> +struct ProgramStateTrait<ReplayWithoutInlining> : + public ProgramStatePartialTrait<void*> { + static void *GDMIndex() { static int index = 0; return &index; } }; } // end ento namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h deleted file mode 100644 index 89b47dc..0000000 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- ExprEngineBuilders.h - "Builder" classes for ExprEngine ---*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines smart builder "references" which are used to marshal -// builders between ExprEngine objects and their related components. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_EXPRENGINE_BUILDERS -#define LLVM_CLANG_GR_EXPRENGINE_BUILDERS -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" -#include "clang/Analysis/Support/SaveAndRestore.h" - -namespace clang { - -namespace ento { - -class StmtNodeBuilderRef { - ExplodedNodeSet &Dst; - StmtNodeBuilder &B; - ExprEngine& Eng; - ExplodedNode *Pred; - const ProgramState *state; - const Stmt *stmt; - const unsigned OldSize; - const bool AutoCreateNode; - SaveAndRestore<bool> OldSink; - SaveOr OldHasGen; - -private: - friend class ExprEngine; - - StmtNodeBuilderRef(); // do not implement - void operator=(const StmtNodeBuilderRef&); // do not implement - - StmtNodeBuilderRef(ExplodedNodeSet &dst, - StmtNodeBuilder &builder, - ExprEngine& eng, - ExplodedNode *pred, - const ProgramState *st, - const Stmt *s, bool auto_create_node) - : Dst(dst), B(builder), Eng(eng), Pred(pred), - state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node), - OldSink(B.BuildSinks), OldHasGen(B.hasGeneratedNode) {} - -public: - - ~StmtNodeBuilderRef() { - // Handle the case where no nodes where generated. Auto-generate that - // contains the updated state if we aren't generating sinks. - if (!B.BuildSinks && Dst.size() == OldSize && !B.hasGeneratedNode) { - if (AutoCreateNode) - B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state); - else - Dst.Add(Pred); - } - } - - const ProgramState *getState() { return state; } - - ProgramStateManager& getStateManager() { - return Eng.getStateManager(); - } - - ExplodedNode *MakeNode(const ProgramState *state) { - return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state); - } -}; - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h new file mode 100644 index 0000000..42adff3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -0,0 +1,107 @@ +//== FunctionSummary.h - Stores summaries of functions. ------------*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a summary of a function gathered/used by static analyzes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H +#define LLVM_CLANG_GR_FUNCTIONSUMMARY_H + +#include "clang/AST/Decl.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/BitVector.h" + +namespace clang { +namespace ento { +typedef llvm::SmallPtrSet<Decl*, 24> SetOfDecls; +typedef llvm::SmallPtrSet<const Decl*, 24> SetOfConstDecls; + +class FunctionSummariesTy { + struct FunctionSummary { + /// True if this function has reached a max block count while inlined from + /// at least one call site. + bool MayReachMaxBlockCount; + + /// Total number of blocks in the function. + unsigned TotalBasicBlocks; + + /// Marks the IDs of the basic blocks visited during the analyzes. + llvm::BitVector VisitedBasicBlocks; + + FunctionSummary() : + MayReachMaxBlockCount(false), + TotalBasicBlocks(0), + VisitedBasicBlocks(0) {} + }; + + typedef llvm::DenseMap<const Decl*, FunctionSummary*> MapTy; + MapTy Map; + +public: + ~FunctionSummariesTy(); + + MapTy::iterator findOrInsertSummary(const Decl *D) { + MapTy::iterator I = Map.find(D); + if (I != Map.end()) + return I; + FunctionSummary *DS = new FunctionSummary(); + I = Map.insert(std::pair<const Decl*, FunctionSummary*>(D, DS)).first; + assert(I != Map.end()); + return I; + } + + void markReachedMaxBlockCount(const Decl* D) { + MapTy::iterator I = findOrInsertSummary(D); + I->second->MayReachMaxBlockCount = true; + } + + bool hasReachedMaxBlockCount(const Decl* D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end()) + return I->second->MayReachMaxBlockCount; + return false; + } + + void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) { + MapTy::iterator I = findOrInsertSummary(D); + llvm::BitVector &Blocks = I->second->VisitedBasicBlocks; + assert(ID < TotalIDs); + if (TotalIDs > Blocks.size()) { + Blocks.resize(TotalIDs); + I->second->TotalBasicBlocks = TotalIDs; + } + Blocks[ID] = true; + } + + unsigned getNumVisitedBasicBlocks(const Decl* D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end()) + return I->second->VisitedBasicBlocks.count(); + return 0; + } + + /// Get the percentage of the reachable blocks. + unsigned getPercentBlocksReachable(const Decl *D) { + MapTy::const_iterator I = Map.find(D); + if (I != Map.end()) + return ((I->second->VisitedBasicBlocks.count() * 100) / + I->second->TotalBasicBlocks); + return 0; + } + + unsigned getTotalNumBasicBlocks(); + unsigned getTotalNumVisitedBasicBlocks(); + +}; + +}} // end clang ento namespaces + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index c9941fe..87bc0df 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -18,7 +18,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/Support/ErrorHandling.h" @@ -73,12 +73,16 @@ public: StackArgumentsSpaceRegionKind, HeapSpaceRegionKind, UnknownSpaceRegionKind, - NonStaticGlobalSpaceRegionKind, StaticGlobalSpaceRegionKind, - BEG_GLOBAL_MEMSPACES = NonStaticGlobalSpaceRegionKind, - END_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, + GlobalInternalSpaceRegionKind, + GlobalSystemSpaceRegionKind, + GlobalImmutableSpaceRegionKind, + BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind, + END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, + BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, + END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind, BEG_MEMSPACES = GenericMemSpaceRegionKind, - END_MEMSPACES = StaticGlobalSpaceRegionKind, + END_MEMSPACES = GlobalImmutableSpaceRegionKind, // Untyped regions. SymbolicRegionKind, AllocaRegionKind, @@ -91,6 +95,7 @@ public: CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS, CXXThisRegionKind, StringRegionKind, + ObjCStringRegionKind, ElementRegionKind, // Decl Regions. BEG_DECL_REGIONS, @@ -118,8 +123,6 @@ public: virtual MemRegionManager* getMemRegionManager() const = 0; - std::string getString() const; - const MemSpaceRegion *getMemorySpace() const; const MemRegion *getBaseRegion() const; @@ -137,10 +140,16 @@ public: /// Compute the offset within the top level memory object. RegionOffset getAsOffset() const; + /// \brief Get a string representation of a region for debug use. + std::string getString() const; + virtual void dumpToStream(raw_ostream &os) const; void dump() const; + /// \brief Print the region for use in diagnostics. + virtual void dumpPretty(raw_ostream &os) const; + Kind getKind() const { return kind; } template<typename RegionTy> const RegionTy* getAs() const; @@ -150,7 +159,7 @@ public: static bool classof(const MemRegion*) { return true; } }; -/// MemSpaceRegion - A memory region that represents and "memory space"; +/// MemSpaceRegion - A memory region that represents a "memory space"; /// for example, the set of global variables, the stack frame, etc. class MemSpaceRegion : public MemRegion { protected: @@ -177,6 +186,7 @@ public: }; class GlobalsSpaceRegion : public MemSpaceRegion { + virtual void anchor(); protected: GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {} @@ -186,7 +196,11 @@ public: return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; } }; - + +/// \class The region of the static variables within the current CodeTextRegion +/// scope. +/// Currently, only the static locals are placed there, so we know that these +/// variables do not get invalidated by calls to other functions. class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { friend class MemRegionManager; @@ -206,23 +220,88 @@ public: return R->getKind() == StaticGlobalSpaceRegionKind; } }; - + +/// \class The region for all the non-static global variables. +/// +/// This class is further split into subclasses for efficient implementation of +/// invalidating a set of related global values as is done in +/// RegionStoreManager::invalidateRegions (instead of finding all the dependent +/// globals, we invalidate the whole parent region). class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { friend class MemRegionManager; - NonStaticGlobalSpaceRegion(MemRegionManager *mgr) - : GlobalsSpaceRegion(mgr, NonStaticGlobalSpaceRegionKind) {} +protected: + NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) + : GlobalsSpaceRegion(mgr, k) {} public: void dumpToStream(raw_ostream &os) const; static bool classof(const MemRegion *R) { - return R->getKind() == NonStaticGlobalSpaceRegionKind; + Kind k = R->getKind(); + return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES && + k <= END_NON_STATIC_GLOBAL_MEMSPACES; } }; - + +/// \class The region containing globals which are defined in system/external +/// headers and are considered modifiable by system calls (ex: errno). +class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { + friend class MemRegionManager; + + GlobalSystemSpaceRegion(MemRegionManager *mgr) + : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {} + +public: + + void dumpToStream(raw_ostream &os) const; + + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalSystemSpaceRegionKind; + } +}; + +/// \class The region containing globals which are considered not to be modified +/// or point to data which could be modified as a result of a function call +/// (system or internal). Ex: Const global scalars would be modeled as part of +/// this region. This region also includes most system globals since they have +/// low chance of being modified. +class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion { + friend class MemRegionManager; + + GlobalImmutableSpaceRegion(MemRegionManager *mgr) + : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {} + +public: + + void dumpToStream(raw_ostream &os) const; + + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalImmutableSpaceRegionKind; + } +}; + +/// \class The region containing globals which can be modified by calls to +/// "internally" defined functions - (for now just) functions other then system +/// calls. +class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { + friend class MemRegionManager; + + GlobalInternalSpaceRegion(MemRegionManager *mgr) + : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {} + +public: + + void dumpToStream(raw_ostream &os) const; + + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalInternalSpaceRegionKind; + } +}; + class HeapSpaceRegion : public MemSpaceRegion { + virtual void anchor(); friend class MemRegionManager; HeapSpaceRegion(MemRegionManager *mgr) @@ -234,6 +313,7 @@ public: }; class UnknownSpaceRegion : public MemSpaceRegion { + virtual void anchor(); friend class MemRegionManager; UnknownSpaceRegion(MemRegionManager *mgr) : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} @@ -266,7 +346,7 @@ public: }; class StackLocalsSpaceRegion : public StackSpaceRegion { -private: + virtual void anchor(); friend class MemRegionManager; StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} @@ -278,6 +358,7 @@ public: class StackArgumentsSpaceRegion : public StackSpaceRegion { private: + virtual void anchor(); friend class MemRegionManager; StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} @@ -291,6 +372,8 @@ public: /// SubRegion - A region that subsets another larger region. Most regions /// are subclasses of SubRegion. class SubRegion : public MemRegion { +private: + virtual void anchor(); protected: const MemRegion* superRegion; SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {} @@ -351,6 +434,8 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { +public: + virtual void anchor(); protected: TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} @@ -371,6 +456,8 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { +public: + virtual void anchor(); protected: TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} @@ -399,6 +486,8 @@ public: class CodeTextRegion : public TypedRegion { +public: + virtual void anchor(); protected: CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: @@ -448,11 +537,11 @@ class BlockTextRegion : public CodeTextRegion { friend class MemRegionManager; const BlockDecl *BD; - AnalysisContext *AC; + AnalysisDeclContext *AC; CanQualType locTy; BlockTextRegion(const BlockDecl *bd, CanQualType lTy, - AnalysisContext *ac, const MemRegion* sreg) + AnalysisDeclContext *ac, const MemRegion* sreg) : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} public: @@ -464,14 +553,14 @@ public: return BD; } - AnalysisContext *getAnalysisContext() const { return AC; } + AnalysisDeclContext *getAnalysisDeclContext() const { return AC; } virtual void dumpToStream(raw_ostream &os) const; void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, - CanQualType, const AnalysisContext*, + CanQualType, const AnalysisDeclContext*, const MemRegion*); static bool classof(const MemRegion* R) { @@ -611,6 +700,40 @@ public: return R->getKind() == StringRegionKind; } }; + +/// The region associated with an ObjCStringLiteral. +class ObjCStringRegion : public TypedValueRegion { + friend class MemRegionManager; + const ObjCStringLiteral* Str; +protected: + + ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg) + : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const ObjCStringLiteral* Str, + const MemRegion* superRegion); + +public: + + const ObjCStringLiteral* getObjCStringLiteral() const { return Str; } + + QualType getValueType() const { + return Str->getType(); + } + + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ProfileRegion(ID, Str, superRegion); + } + + void dumpToStream(raw_ostream &os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == ObjCStringRegionKind; + } +}; /// CompoundLiteralRegion - A memory region representing a compound literal. /// Compound literals are essentially temporaries that are stack allocated @@ -695,6 +818,8 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == VarRegionKind; } + + void dumpPretty(raw_ostream &os) const; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -734,9 +859,6 @@ class FieldRegion : public DeclRegion { : DeclRegion(fd, sReg, FieldRegionKind) {} public: - - void dumpToStream(raw_ostream &os) const; - const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } QualType getValueType() const { @@ -754,23 +876,23 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == FieldRegionKind; } + + void dumpToStream(raw_ostream &os) const; + void dumpPretty(raw_ostream &os) const; }; class ObjCIvarRegion : public DeclRegion { friend class MemRegionManager; - ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg) - : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {} + ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg); static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd, - const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind); - } + const MemRegion* superRegion); public: - const ObjCIvarDecl *getDecl() const { return cast<ObjCIvarDecl>(D); } - QualType getValueType() const { return getDecl()->getType(); } + const ObjCIvarDecl *getDecl() const; + QualType getValueType() const; void dumpToStream(raw_ostream &os) const; @@ -803,6 +925,7 @@ public: void dump() const; }; +/// \brief ElementRegin is used to represent both array elements and casts. class ElementRegion : public TypedValueRegion { friend class MemRegionManager; @@ -915,7 +1038,10 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - NonStaticGlobalSpaceRegion *globals; + GlobalInternalSpaceRegion *InternalGlobals; + GlobalSystemSpaceRegion *SystemGlobals; + GlobalImmutableSpaceRegion *ImmutableGlobals; + llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> StackLocalsSpaceRegions; @@ -930,7 +1056,8 @@ class MemRegionManager { public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {} + : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0), + heap(0), unknown(0), code(0) {} ~MemRegionManager(); @@ -950,7 +1077,9 @@ public: /// getGlobalsRegion - Retrieve the memory region associated with /// global variables. - const GlobalsSpaceRegion *getGlobalsRegion(const CodeTextRegion *R = 0); + const GlobalsSpaceRegion *getGlobalsRegion( + MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind, + const CodeTextRegion *R = 0); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". @@ -980,7 +1109,9 @@ public: /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. const SymbolicRegion* getSymbolicRegion(SymbolRef sym); - const StringRegion* getStringRegion(const StringLiteral* Str); + const StringRegion *getStringRegion(const StringLiteral* Str); + + const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str); /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and LocationContext. @@ -1038,7 +1169,7 @@ public: const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, - AnalysisContext *AC); + AnalysisDeclContext *AC); /// getBlockDataRegion - Get the memory region associated with an instance /// of a block. Unlike many other MemRegions, the LocationContext* @@ -1047,11 +1178,6 @@ public: const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc = NULL); - bool isGlobalsRegion(const MemRegion* R) { - assert(R); - return R == globals; - } - private: template <typename RegionTy, typename A1> RegionTy* getRegion(const A1 a1); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index add3479..d8aec09 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -19,82 +19,72 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Compiler.h" namespace clang { namespace ento { +using llvm::StrInStrNoCase; /// \brief Represents both explicit ObjC message expressions and implicit /// messages that are sent for handling properties in dot syntax. class ObjCMessage { - const Expr *MsgOrPropE; - const Expr *OriginE; - bool IsPropSetter; - SVal SetterArgV; - -protected: - ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV) - : MsgOrPropE(E), OriginE(origE), - IsPropSetter(isSetter), SetterArgV(setArgV) { } - + const ObjCMessageExpr *Msg; + const ObjCPropertyRefExpr *PE; + const bool IsPropSetter; public: - ObjCMessage() : MsgOrPropE(0), OriginE(0) { } + ObjCMessage() : Msg(0), PE(0), IsPropSetter(false) {} - ObjCMessage(const ObjCMessageExpr *E) - : MsgOrPropE(E), OriginE(E) { + ObjCMessage(const ObjCMessageExpr *E, const ObjCPropertyRefExpr *pe = 0, + bool isSetter = false) + : Msg(E), PE(pe), IsPropSetter(isSetter) { assert(E && "should not be initialized with null expression"); } - bool isValid() const { return MsgOrPropE != 0; } - bool isInvalid() const { return !isValid(); } + bool isValid() const { return Msg; } + + bool isPureMessageExpr() const { return !PE; } - bool isMessageExpr() const { - return isValid() && isa<ObjCMessageExpr>(MsgOrPropE); - } + bool isPropertyGetter() const { return PE && !IsPropSetter; } - bool isPropertyGetter() const { - return isValid() && - isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter; + bool isPropertySetter() const { + return IsPropSetter; } - bool isPropertySetter() const { - return isValid() && - isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter; + const Expr *getMessageExpr() const { + return Msg; } - - const Expr *getOriginExpr() const { return OriginE; } - QualType getType(ASTContext &ctx) const; + QualType getType(ASTContext &ctx) const { + return Msg->getType(); + } QualType getResultType(ASTContext &ctx) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - if (const ObjCMethodDecl *MD = msgE->getMethodDecl()) - return MD->getResultType(); + if (const ObjCMethodDecl *MD = Msg->getMethodDecl()) + return MD->getResultType(); return getType(ctx); } - ObjCMethodFamily getMethodFamily() const; + ObjCMethodFamily getMethodFamily() const { + return Msg->getMethodFamily(); + } - Selector getSelector() const; + Selector getSelector() const { + return Msg->getSelector(); + } const Expr *getInstanceReceiver() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getInstanceReceiver(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (propE->isObjectReceiver()) - return propE->getBase(); - return 0; + return Msg->getInstanceReceiver(); } - SVal getInstanceReceiverSVal(const ProgramState *State, + SVal getInstanceReceiverSVal(ProgramStateRef State, const LocationContext *LC) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); if (!isInstanceMessage()) return UndefinedVal(); if (const Expr *Ex = getInstanceReceiver()) - return State->getSValAsScalarOrLoc(Ex); + return State->getSValAsScalarOrLoc(Ex, LC); // An instance message with no expression means we are sending to super. // In this case the object reference is the same as 'self'. @@ -104,99 +94,66 @@ public: } bool isInstanceMessage() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->isInstanceMessage(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - // FIXME: 'super' may be super class. - return propE->isObjectReceiver() || propE->isSuperReceiver(); + return Msg->isInstanceMessage(); } - const ObjCMethodDecl *getMethodDecl() const; - - const ObjCInterfaceDecl *getReceiverInterface() const; - - SourceLocation getSuperLoc() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getSuperLoc(); - return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation(); + const ObjCMethodDecl *getMethodDecl() const { + return Msg->getMethodDecl(); } - const Expr *getMsgOrPropExpr() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - return MsgOrPropE; + const ObjCInterfaceDecl *getReceiverInterface() const { + return Msg->getReceiverInterface(); } - SourceRange getSourceRange() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - return MsgOrPropE->getSourceRange(); + SourceLocation getSuperLoc() const { + if (PE) + return PE->getReceiverLocation(); + return Msg->getSuperLoc(); + } + + SourceRange getSourceRange() const LLVM_READONLY { + if (PE) + return PE->getSourceRange(); + return Msg->getSourceRange(); } unsigned getNumArgs() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getNumArgs(); - return isPropertySetter() ? 1 : 0; + return Msg->getNumArgs(); } - SVal getArgSVal(unsigned i, const ProgramState *state) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); + SVal getArgSVal(unsigned i, + const LocationContext *LCtx, + ProgramStateRef state) const { assert(i < getNumArgs() && "Invalid index for argument"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return state->getSVal(msgE->getArg(i)); - assert(isPropertySetter()); - return SetterArgV; + return state->getSVal(Msg->getArg(i), LCtx); } QualType getArgType(unsigned i) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); assert(i < getNumArgs() && "Invalid index for argument"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getArg(i)->getType(); - assert(isPropertySetter()); - return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType(); + return Msg->getArg(i)->getType(); } - const Expr *getArgExpr(unsigned i) const; + const Expr *getArgExpr(unsigned i) const { + assert(i < getNumArgs() && "Invalid index for argument"); + return Msg->getArg(i); + } SourceRange getArgSourceRange(unsigned i) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - assert(i < getNumArgs() && "Invalid index for argument"); - if (const Expr *argE = getArgExpr(i)) - return argE->getSourceRange(); - return OriginE->getSourceRange(); + const Expr *argE = getArgExpr(i); + return argE->getSourceRange(); } SourceRange getReceiverSourceRange() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getReceiverRange(); - - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (propE->isObjectReceiver()) - return propE->getBase()->getSourceRange(); + if (PE) { + if (PE->isObjectReceiver()) + return PE->getBase()->getSourceRange(); + } + else { + return Msg->getReceiverRange(); + } // FIXME: This isn't a range. - return propE->getReceiverLocation(); - } -}; - -class ObjCPropertyGetter : public ObjCMessage { -public: - ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE) - : ObjCMessage(propE, originE, false, SVal()) { - assert(propE && originE && - "should not be initialized with null expressions"); - } -}; - -class ObjCPropertySetter : public ObjCMessage { -public: - ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE, - SVal argV) - : ObjCMessage(propE, storeE, true, argV) { - assert(propE && storeE &&"should not be initialized with null expressions"); + return PE->getReceiverLocation(); } }; @@ -205,14 +162,18 @@ public: class CallOrObjCMessage { llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE; ObjCMessage Msg; - const ProgramState *State; + ProgramStateRef State; + const LocationContext *LCtx; public: - CallOrObjCMessage(const CallExpr *callE, const ProgramState *state) - : CallE(callE), State(state) {} - CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state) - : CallE(consE), State(state) {} - CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state) - : CallE((CallExpr *)0), Msg(msg), State(state) {} + CallOrObjCMessage(const CallExpr *callE, ProgramStateRef state, + const LocationContext *lctx) + : CallE(callE), State(state), LCtx(lctx) {} + CallOrObjCMessage(const CXXConstructExpr *consE, ProgramStateRef state, + const LocationContext *lctx) + : CallE(consE), State(state), LCtx(lctx) {} + CallOrObjCMessage(const ObjCMessage &msg, ProgramStateRef state, + const LocationContext *lctx) + : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {} QualType getResultType(ASTContext &ctx) const; @@ -233,9 +194,19 @@ public: return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE); } + /// Check if the callee is declared in the system header. + bool isInSystemHeader() const { + if (const Decl *FD = getDecl()) { + const SourceManager &SM = + State->getStateManager().getContext().getSourceManager(); + return SM.isInSystemHeader(FD->getLocation()); + } + return false; + } + const Expr *getOriginExpr() const { if (!CallE) - return Msg.getOriginExpr(); + return Msg.getMessageExpr(); if (const CXXConstructExpr *Ctor = CallE.dyn_cast<const CXXConstructExpr *>()) return Ctor; @@ -246,6 +217,9 @@ public: SVal getCXXCallee() const; SVal getInstanceMessageReceiver(const LocationContext *LC) const; + /// Get the declaration of the function or method. + const Decl *getDecl() const; + unsigned getNumArgs() const { if (!CallE) return Msg.getNumArgs(); @@ -258,8 +232,8 @@ public: SVal getArgSVal(unsigned i) const { assert(i < getNumArgs()); if (!CallE) - return Msg.getArgSVal(i, State); - return State->getSVal(getArg(i)); + return Msg.getArgSVal(i, LCtx, State); + return State->getSVal(getArg(i), LCtx); } const Expr *getArg(unsigned i) const { @@ -283,6 +257,34 @@ public: assert(isObjCMessage()); return Msg.getReceiverSourceRange(); } + + /// \brief Check if the name corresponds to a CoreFoundation or CoreGraphics + /// function that allows objects to escape. + /// + /// Many methods allow a tracked object to escape. For example: + /// + /// CFMutableDictionaryRef x = CFDictionaryCreateMutable(..., customDeallocator); + /// CFDictionaryAddValue(y, key, x); + /// + /// We handle this and similar cases with the following heuristic. If the + /// function name contains "InsertValue", "SetValue", "AddValue", + /// "AppendValue", or "SetAttribute", then we assume that arguments may + /// escape. + // + // TODO: To reduce false negatives here, we should track the container + // allocation site and check if a proper deallocator was set there. + static bool isCFCGAllowingEscape(StringRef FName) { + if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) + if (StrInStrNoCase(FName, "InsertValue") != StringRef::npos|| + StrInStrNoCase(FName, "AddValue") != StringRef::npos || + StrInStrNoCase(FName, "SetValue") != StringRef::npos || + StrInStrNoCase(FName, "WithData") != StringRef::npos || + StrInStrNoCase(FName, "AppendValue") != StringRef::npos|| + StrInStrNoCase(FName, "SetAttribute") != StringRef::npos) { + return true; + } + return false; + } }; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index edae06e..360d648 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -19,6 +19,8 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" @@ -33,7 +35,7 @@ class ASTContext; namespace ento { -class ProgramStateManager; +class CallOrObjCMessage; typedef ConstraintManager* (*ConstraintManagerCreator)(ProgramStateManager&, SubEngine&); @@ -54,8 +56,6 @@ template <typename T> struct ProgramStateTrait { } }; -class ProgramStateManager; - /// \class ProgramState /// ProgramState - This class encapsulates: /// @@ -88,12 +88,11 @@ private: /// makeWithStore - Return a ProgramState with the same values as the current /// state with the exception of using the specified Store. - const ProgramState *makeWithStore(const StoreRef &store) const; + ProgramStateRef makeWithStore(const StoreRef &store) const; void setStore(const StoreRef &storeRef); public: - /// This ctor is used when creating the first ProgramState object. ProgramState(ProgramStateManager *mgr, const Environment& env, StoreRef st, GenericDataMap gdm); @@ -107,9 +106,6 @@ public: /// Return the ProgramStateManager associated with this state. ProgramStateManager &getStateManager() const { return *stateMgr; } - /// Return true if this state is referenced by a persistent ExplodedNode. - bool referencedByExplodedNode() const { return refCount > 0; } - /// getEnvironment - Return the environment associated with this state. /// The environment is the mapping from expressions to values. const Environment& getEnvironment() const { return Env; } @@ -168,17 +164,18 @@ public: // If no new state is feasible, NULL is returned. // - const ProgramState *assume(DefinedOrUnknownSVal cond, bool assumption) const; + ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const; /// This method assumes both "true" and "false" for 'cond', and /// returns both corresponding states. It's shorthand for doing /// 'assume' twice. - std::pair<const ProgramState*, const ProgramState*> + std::pair<ProgramStateRef , ProgramStateRef > assume(DefinedOrUnknownSVal cond) const; - const ProgramState *assumeInBound(DefinedOrUnknownSVal idx, + ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, - bool assumption) const; + bool assumption, + QualType IndexType = QualType()) const; /// Utility method for getting regions. const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; @@ -189,49 +186,50 @@ public: /// BindCompoundLiteral - Return the state that has the bindings currently /// in this state plus the bindings for the CompoundLiteral. - const ProgramState *bindCompoundLiteral(const CompoundLiteralExpr *CL, + ProgramStateRef bindCompoundLiteral(const CompoundLiteralExpr *CL, const LocationContext *LC, SVal V) const; /// Create a new state by binding the value 'V' to the statement 'S' in the /// state's environment. - const ProgramState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; + ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx, + SVal V, bool Invalidate = true) const; /// Create a new state by binding the value 'V' and location 'locaton' to the /// statement 'S' in the state's environment. - const ProgramState *bindExprAndLocation(const Stmt *S, SVal location, SVal V) - const; + ProgramStateRef bindExprAndLocation(const Stmt *S, + const LocationContext *LCtx, + SVal location, SVal V) const; - const ProgramState *bindDecl(const VarRegion *VR, SVal V) const; + ProgramStateRef bindDecl(const VarRegion *VR, SVal V) const; - const ProgramState *bindDeclWithNoInit(const VarRegion *VR) const; + ProgramStateRef bindDeclWithNoInit(const VarRegion *VR) const; - const ProgramState *bindLoc(Loc location, SVal V) const; + ProgramStateRef bindLoc(Loc location, SVal V) const; - const ProgramState *bindLoc(SVal location, SVal V) const; + ProgramStateRef bindLoc(SVal location, SVal V) const; - const ProgramState *bindDefault(SVal loc, SVal V) const; + ProgramStateRef bindDefault(SVal loc, SVal V) const; - const ProgramState *unbindLoc(Loc LV) const; + ProgramStateRef unbindLoc(Loc LV) const; /// invalidateRegions - Returns the state with bindings for the given regions /// cleared from the store. The regions are provided as a continuous array /// from Begin to End. Optionally invalidates global regions as well. - const ProgramState *invalidateRegions(ArrayRef<const MemRegion *> Regions, - const Expr *E, unsigned BlockCount, - StoreManager::InvalidatedSymbols *IS = 0, - bool invalidateGlobals = false) const; + ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions, + const Expr *E, unsigned BlockCount, + const LocationContext *LCtx, + StoreManager::InvalidatedSymbols *IS = 0, + const CallOrObjCMessage *Call = 0) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. - const ProgramState *enterStackFrame(const StackFrameContext *frame) const; + ProgramStateRef enterStackFrame(const LocationContext *callerCtx, + const StackFrameContext *calleeCtx) const; /// Get the lvalue for a variable reference. Loc getLValue(const VarDecl *D, const LocationContext *LC) const; - /// Get the lvalue for a StringLiteral. - Loc getLValue(const StringLiteral *literal) const; - Loc getLValue(const CompoundLiteralExpr *literal, const LocationContext *LC) const; @@ -247,15 +245,20 @@ public: const llvm::APSInt *getSymVal(SymbolRef sym) const; /// Returns the SVal bound to the statement 'S' in the state's environment. - SVal getSVal(const Stmt *S, bool useOnlyDirectBindings = false) const; + SVal getSVal(const Stmt *S, const LocationContext *LCtx, + bool useOnlyDirectBindings = false) const; - SVal getSValAsScalarOrLoc(const Stmt *Ex) const; + SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const; + /// \brief Return the value bound to the specified location. + /// Returns UnknownVal() if none found. SVal getSVal(Loc LV, QualType T = QualType()) const; /// Returns the "raw" SVal bound to LV before any value simplfication. SVal getRawSVal(Loc LV, QualType T= QualType()) const; + /// \brief Return the value bound to the specified location. + /// Returns UnknownVal() if none found. SVal getSVal(const MemRegion* R) const; SVal getSValAsScalarOrLoc(const MemRegion *R) const; @@ -288,6 +291,25 @@ public: scanReachableSymbols(const MemRegion * const *beg, const MemRegion * const *end) const; + /// Create a new state in which the statement is marked as tainted. + ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx, + TaintTagType Kind = TaintTagGeneric) const; + + /// Create a new state in which the symbol is marked as tainted. + ProgramStateRef addTaint(SymbolRef S, + TaintTagType Kind = TaintTagGeneric) const; + + /// Create a new state in which the region symbol is marked as tainted. + ProgramStateRef addTaint(const MemRegion *R, + TaintTagType Kind = TaintTagGeneric) const; + + /// Check if the statement is tainted in the current state. + bool isTainted(const Stmt *S, const LocationContext *LCtx, + TaintTagType Kind = TaintTagGeneric) const; + bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const; + bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const; + bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const; + //==---------------------------------------------------------------------==// // Accessing the Generic Data Map (GDM). //==---------------------------------------------------------------------==// @@ -295,7 +317,7 @@ public: void *const* FindGDM(void *K) const; template<typename T> - const ProgramState *add(typename ProgramStateTrait<T>::key_type K) const; + ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const; template <typename T> typename ProgramStateTrait<T>::data_type @@ -315,23 +337,23 @@ public: template<typename T> - const ProgramState *remove(typename ProgramStateTrait<T>::key_type K) const; + ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const; template<typename T> - const ProgramState *remove(typename ProgramStateTrait<T>::key_type K, + ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::context_type C) const; template <typename T> - const ProgramState *remove() const; + ProgramStateRef remove() const; template<typename T> - const ProgramState *set(typename ProgramStateTrait<T>::data_type D) const; + ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const; template<typename T> - const ProgramState *set(typename ProgramStateTrait<T>::key_type K, + ProgramStateRef set(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::value_type E) const; template<typename T> - const ProgramState *set(typename ProgramStateTrait<T>::key_type K, + ProgramStateRef set(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::value_type E, typename ProgramStateTrait<T>::context_type C) const; @@ -342,61 +364,25 @@ public: } // Pretty-printing. - void print(raw_ostream &Out, CFG &C, const char *nl = "\n", + void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "") const; + void printDOT(raw_ostream &Out) const; + void printTaint(raw_ostream &Out, const char *nl = "\n", + const char *sep = "") const; - void printStdErr(CFG &C) const; - - void printDOT(raw_ostream &Out, CFG &C) const; + void dump() const; + void dumpTaint() const; private: - /// Increments the number of times this state is referenced by ExplodeNodes. - void incrementReferenceCount() { ++refCount; } - - /// Decrement the number of times this state is referenced by ExplodeNodes. - void decrementReferenceCount() { - assert(refCount > 0); - --refCount; - } + friend void ProgramStateRetain(const ProgramState *state); + friend void ProgramStateRelease(const ProgramState *state); - const ProgramState * + ProgramStateRef invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned BlockCount, + const LocationContext *LCtx, StoreManager::InvalidatedSymbols &IS, - bool invalidateGlobals) const; -}; - -class ProgramStateSet { - typedef llvm::SmallPtrSet<const ProgramState*,5> ImplTy; - ImplTy Impl; -public: - ProgramStateSet() {} - - inline void Add(const ProgramState *St) { - Impl.insert(St); - } - - typedef ImplTy::const_iterator iterator; - - inline unsigned size() const { return Impl.size(); } - inline bool empty() const { return Impl.empty(); } - - inline iterator begin() const { return Impl.begin(); } - inline iterator end() const { return Impl.end(); } - - class AutoPopulate { - ProgramStateSet &S; - unsigned StartSize; - const ProgramState *St; - public: - AutoPopulate(ProgramStateSet &s, const ProgramState *st) - : S(s), StartSize(S.size()), St(st) {} - - ~AutoPopulate() { - if (StartSize == S.size()) - S.Add(St); - } - }; + const CallOrObjCMessage *Call) const; }; //===----------------------------------------------------------------------===// @@ -405,13 +391,14 @@ public: class ProgramStateManager { friend class ProgramState; + friend void ProgramStateRelease(const ProgramState *state); private: /// Eng - The SubEngine that owns this state manager. SubEngine *Eng; /* Can be null. */ EnvironmentManager EnvMgr; - llvm::OwningPtr<StoreManager> StoreMgr; - llvm::OwningPtr<ConstraintManager> ConstraintMgr; + OwningPtr<StoreManager> StoreMgr; + OwningPtr<ConstraintManager> ConstraintMgr; ProgramState::GenericDataMap::Factory GDMFactory; @@ -423,14 +410,10 @@ private: llvm::FoldingSet<ProgramState> StateSet; /// Object that manages the data for all created SVals. - llvm::OwningPtr<SValBuilder> svalBuilder; + OwningPtr<SValBuilder> svalBuilder; /// A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator &Alloc; - - /// A vector of recently allocated ProgramStates that can potentially be - /// reused. - std::vector<ProgramState *> recentlyAllocatedStates; /// A vector of ProgramStates that we can reuse. std::vector<ProgramState *> freeStates; @@ -465,7 +448,7 @@ public: ~ProgramStateManager(); - const ProgramState *getInitialState(const LocationContext *InitLoc); + ProgramStateRef getInitialState(const LocationContext *InitLoc); ASTContext &getContext() { return svalBuilder->getContext(); } const ASTContext &getContext() const { return svalBuilder->getContext(); } @@ -501,13 +484,13 @@ public: ConstraintManager& getConstraintManager() { return *ConstraintMgr; } SubEngine* getOwningEngine() { return Eng; } - const ProgramState *removeDeadBindings(const ProgramState *St, + ProgramStateRef removeDeadBindings(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper& SymReaper); /// Marshal a new state for the callee in another translation unit. /// 'state' is owned by the caller's engine. - const ProgramState *MarshalState(const ProgramState *state, const StackFrameContext *L); + ProgramStateRef MarshalState(ProgramStateRef state, const StackFrameContext *L); public: @@ -516,31 +499,27 @@ public: } // Methods that manipulate the GDM. - const ProgramState *addGDM(const ProgramState *St, void *Key, void *Data); - const ProgramState *removeGDM(const ProgramState *state, void *Key); + ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data); + ProgramStateRef removeGDM(ProgramStateRef state, void *Key); // Methods that query & manipulate the Store. - void iterBindings(const ProgramState *state, StoreManager::BindingsHandler& F) { + void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) { StoreMgr->iterBindings(state->getStore(), F); } - const ProgramState *getPersistentState(ProgramState &Impl); - const ProgramState *getPersistentStateWithGDM(const ProgramState *FromState, - const ProgramState *GDMState); + ProgramStateRef getPersistentState(ProgramState &Impl); + ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, + ProgramStateRef GDMState); - bool haveEqualEnvironments(const ProgramState * S1, const ProgramState * S2) { + bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) { return S1->Env == S2->Env; } - bool haveEqualStores(const ProgramState * S1, const ProgramState * S2) { + bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) { return S1->store == S2->store; } - /// Periodically called by ExprEngine to recycle ProgramStates that were - /// created but never used for creating an ExplodedNode. - void recycleUnusedStates(); - //==---------------------------------------------------------------------==// // Generic Data Map methods. //==---------------------------------------------------------------------==// @@ -561,13 +540,13 @@ public: // Trait based GDM dispatch. template <typename T> - const ProgramState *set(const ProgramState *st, typename ProgramStateTrait<T>::data_type D) { + ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) { return addGDM(st, ProgramStateTrait<T>::GDMIndex(), ProgramStateTrait<T>::MakeVoidPtr(D)); } template<typename T> - const ProgramState *set(const ProgramState *st, + ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::value_type V, typename ProgramStateTrait<T>::context_type C) { @@ -577,7 +556,7 @@ public: } template <typename T> - const ProgramState *add(const ProgramState *st, + ProgramStateRef add(ProgramStateRef st, typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::context_type C) { return addGDM(st, ProgramStateTrait<T>::GDMIndex(), @@ -585,7 +564,7 @@ public: } template <typename T> - const ProgramState *remove(const ProgramState *st, + ProgramStateRef remove(ProgramStateRef st, typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::context_type C) { @@ -594,7 +573,7 @@ public: } template <typename T> - const ProgramState *remove(const ProgramState *st) { + ProgramStateRef remove(ProgramStateRef st) { return removeGDM(st, ProgramStateTrait<T>::GDMIndex()); } @@ -611,11 +590,11 @@ public: return ProgramStateTrait<T>::MakeContext(p); } - const llvm::APSInt* getSymVal(const ProgramState *St, SymbolRef sym) { + const llvm::APSInt* getSymVal(ProgramStateRef St, SymbolRef sym) { return ConstraintMgr->getSymVal(St, sym); } - void EndPath(const ProgramState *St) { + void EndPath(ProgramStateRef St) { ConstraintMgr->EndPath(St); } }; @@ -626,11 +605,12 @@ public: //===----------------------------------------------------------------------===// inline const VarRegion* ProgramState::getRegion(const VarDecl *D, - const LocationContext *LC) const { + const LocationContext *LC) const +{ return getStateManager().getRegionManager().getVarRegion(D, LC); } -inline const ProgramState *ProgramState::assume(DefinedOrUnknownSVal Cond, +inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond, bool Assumption) const { if (Cond.isUnknown()) return this; @@ -639,7 +619,7 @@ inline const ProgramState *ProgramState::assume(DefinedOrUnknownSVal Cond, Assumption); } -inline std::pair<const ProgramState*, const ProgramState*> +inline std::pair<ProgramStateRef , ProgramStateRef > ProgramState::assume(DefinedOrUnknownSVal Cond) const { if (Cond.isUnknown()) return std::make_pair(this, this); @@ -648,7 +628,7 @@ ProgramState::assume(DefinedOrUnknownSVal Cond) const { cast<DefinedSVal>(Cond)); } -inline const ProgramState *ProgramState::bindLoc(SVal LV, SVal V) const { +inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); } @@ -657,10 +637,6 @@ inline Loc ProgramState::getLValue(const VarDecl *VD, return getStateManager().StoreMgr->getLValueVar(VD, LC); } -inline Loc ProgramState::getLValue(const StringLiteral *literal) const { - return getStateManager().StoreMgr->getLValueString(literal); -} - inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); @@ -684,27 +660,32 @@ inline const llvm::APSInt *ProgramState::getSymVal(SymbolRef sym) const { return getStateManager().getSymVal(this, sym); } -inline SVal ProgramState::getSVal(const Stmt *Ex, bool useOnlyDirectBindings) const{ - return Env.getSVal(Ex, *getStateManager().svalBuilder, +inline SVal ProgramState::getSVal(const Stmt *Ex, const LocationContext *LCtx, + bool useOnlyDirectBindings) const{ + return Env.getSVal(EnvironmentEntry(Ex, LCtx), + *getStateManager().svalBuilder, useOnlyDirectBindings); } -inline SVal ProgramState::getSValAsScalarOrLoc(const Stmt *S) const { +inline SVal +ProgramState::getSValAsScalarOrLoc(const Stmt *S, + const LocationContext *LCtx) const { if (const Expr *Ex = dyn_cast<Expr>(S)) { QualType T = Ex->getType(); if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType()) - return getSVal(S); + return getSVal(S, LCtx); } return UnknownVal(); } inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const { - return getStateManager().StoreMgr->Retrieve(getStore(), LV, T); + return getStateManager().StoreMgr->getBinding(getStore(), LV, T); } inline SVal ProgramState::getSVal(const MemRegion* R) const { - return getStateManager().StoreMgr->Retrieve(getStore(), loc::MemRegionVal(R)); + return getStateManager().StoreMgr->getBinding(getStore(), + loc::MemRegionVal(R)); } inline BasicValueFactory &ProgramState::getBasicVals() const { @@ -716,7 +697,7 @@ inline SymbolManager &ProgramState::getSymbolManager() const { } template<typename T> -const ProgramState *ProgramState::add(typename ProgramStateTrait<T>::key_type K) const { +ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const { return getStateManager().add<T>(this, K, get_context<T>()); } @@ -726,34 +707,34 @@ typename ProgramStateTrait<T>::context_type ProgramState::get_context() const { } template<typename T> -const ProgramState *ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const { +ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const { return getStateManager().remove<T>(this, K, get_context<T>()); } template<typename T> -const ProgramState *ProgramState::remove(typename ProgramStateTrait<T>::key_type K, +ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::context_type C) const { return getStateManager().remove<T>(this, K, C); } template <typename T> -const ProgramState *ProgramState::remove() const { +ProgramStateRef ProgramState::remove() const { return getStateManager().remove<T>(this); } template<typename T> -const ProgramState *ProgramState::set(typename ProgramStateTrait<T>::data_type D) const { +ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const { return getStateManager().set<T>(this, D); } template<typename T> -const ProgramState *ProgramState::set(typename ProgramStateTrait<T>::key_type K, +ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::value_type E) const { return getStateManager().set<T>(this, K, E, get_context<T>()); } template<typename T> -const ProgramState *ProgramState::set(typename ProgramStateTrait<T>::key_type K, +ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K, typename ProgramStateTrait<T>::value_type E, typename ProgramStateTrait<T>::context_type C) const { return getStateManager().set<T>(this, K, E, C); @@ -785,15 +766,16 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg, /// A Utility class that allows to visit the reachable symbols using a custom /// SymbolVisitor. class ScanReachableSymbols : public SubRegionMap::Visitor { + virtual void anchor(); typedef llvm::DenseMap<const void*, unsigned> VisitedItems; VisitedItems visited; - const ProgramState *state; + ProgramStateRef state; SymbolVisitor &visitor; - llvm::OwningPtr<SubRegionMap> SRM; + OwningPtr<SubRegionMap> SRM; public: - ScanReachableSymbols(const ProgramState *st, SymbolVisitor& v) + ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v) : state(st), visitor(v) {} bool scan(nonloc::CompoundVal val); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index b80d494..1c7bedb 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -9,8 +9,8 @@ // // This file defines partial implementations of template specializations of // the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState -// to implement set/get methods for mapulating a ProgramState's -// generic data map. +// to implement set/get methods for manipulating a ProgramState's +// generic data map. // //===----------------------------------------------------------------------===// @@ -176,7 +176,20 @@ namespace ento { return (void*) (uintptr_t) d; } }; - + + // Partial specialization for void*. + template <> struct ProgramStatePartialTrait<void*> { + typedef void *data_type; + + static inline data_type MakeData(void *const* p) { + return p ? *p + : data_type(); + } + static inline void *MakeVoidPtr(data_type d) { + return d; + } + }; + } // end GR namespace } // end clang namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h new file mode 100644 index 0000000..371f3c5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h @@ -0,0 +1,43 @@ +//== ProgramState_Fwd.h - Incomplete declarations of ProgramState -*- C++ -*--=/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PROGRAMSTATE_FWD_H +#define LLVM_CLANG_PROGRAMSTATE_FWD_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" + +namespace clang { +namespace ento { + class ProgramState; + class ProgramStateManager; + void ProgramStateRetain(const ProgramState *state); + void ProgramStateRelease(const ProgramState *state); +} +} + +namespace llvm { + template <> struct IntrusiveRefCntPtrInfo<const clang::ento::ProgramState> { + static void retain(const clang::ento::ProgramState *state) { + clang::ento::ProgramStateRetain(state); + } + static void release(const clang::ento::ProgramState *state) { + clang::ento::ProgramStateRelease(state); + } + }; +} + +namespace clang { +namespace ento { + typedef IntrusiveRefCntPtr<const ProgramState> ProgramStateRef; +} +} + +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 17233e1..4ad36f9 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -17,17 +17,19 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" namespace clang { -namespace ento { +class CXXBoolLiteralExpr; -class ProgramState; +namespace ento { class SValBuilder { + virtual void anchor(); protected: ASTContext &Context; @@ -48,11 +50,13 @@ protected: /// The width of the scalar type used for array indices. const unsigned ArrayIndexWidth; + virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0; + virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0; + public: // FIXME: Make these protected again once RegionStoreManager correctly // handles loads from different bound value types. - virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0; - virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0; + virtual SVal dispatchCast(SVal val, QualType castTy) = 0; public: SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, @@ -66,29 +70,54 @@ public: virtual ~SValBuilder() {} + bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) { + return haveSameType(Sym1->getType(Context), Sym2->getType(Context)); + } + + bool haveSameType(QualType Ty1, QualType Ty2) { + // FIXME: Remove the second disjunct when we support symbolic + // truncation/extension. + return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) || + (Ty2->isIntegerType() && Ty2->isIntegerType())); + } + SVal evalCast(SVal val, QualType castTy, QualType originalType); virtual SVal evalMinus(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0; - virtual SVal evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op, + /// Create a new value which represents a binary expression with two non + /// location operands. + virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLL(const ProgramState *state, BinaryOperator::Opcode op, + /// Create a new value which represents a binary expression with two memory + /// location operands. + virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLN(const ProgramState *state, BinaryOperator::Opcode op, + /// Create a new value which represents a binary expression with a memory + /// location and non location operands. For example, this would be used to + /// evaluate a pointer arithmetic operation. + virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) = 0; - /// getKnownValue - evaluates a given SVal. If the SVal has only one possible - /// (integer) value, that value is returned. Otherwise, returns NULL. - virtual const llvm::APSInt *getKnownValue(const ProgramState *state, SVal val) = 0; + /// Evaluates a given SVal. If the SVal has only one possible (integer) value, + /// that value is returned. Otherwise, returns NULL. + virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0; - SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op, + /// Handles generation of the value in case the builder is not smart enough to + /// handle the given binary expression. Depending on the state, decides to + /// either keep the expression or forget the history and generate an + /// UnknownVal. + SVal makeGenericVal(ProgramStateRef state, BinaryOperator::Opcode op, + NonLoc lhs, NonLoc rhs, QualType resultTy); + + SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type); - DefinedOrUnknownSVal evalEQ(const ProgramState *state, DefinedOrUnknownSVal lhs, + DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs); ASTContext &getContext() { return Context; } @@ -115,28 +144,47 @@ public: // Forwarding methods to SymbolManager. - const SymbolConjured* getConjuredSymbol(const Stmt *stmt, QualType type, + const SymbolConjured* getConjuredSymbol(const Stmt *stmt, + const LocationContext *LCtx, + QualType type, unsigned visitCount, const void *symbolTag = 0) { - return SymMgr.getConjuredSymbol(stmt, type, visitCount, symbolTag); + return SymMgr.getConjuredSymbol(stmt, LCtx, type, visitCount, symbolTag); } - const SymbolConjured* getConjuredSymbol(const Expr *expr, unsigned visitCount, + const SymbolConjured* getConjuredSymbol(const Expr *expr, + const LocationContext *LCtx, + unsigned visitCount, const void *symbolTag = 0) { - return SymMgr.getConjuredSymbol(expr, visitCount, symbolTag); + return SymMgr.getConjuredSymbol(expr, LCtx, visitCount, symbolTag); } - /// makeZeroVal - Construct an SVal representing '0' for the specified type. + /// Construct an SVal representing '0' for the specified type. DefinedOrUnknownSVal makeZeroVal(QualType type); - /// getRegionValueSymbolVal - make a unique symbol for value of region. + /// Make a unique symbol for value of region. DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region); + /// \brief Create a new symbol with a unique 'name'. + /// + /// We resort to conjured symbols when we cannot construct a derived symbol. + /// The advantage of symbols derived/built from other symbols is that we + /// preserve the relation between related(or even equivalent) expressions, so + /// conjured symbols should be used sparingly. DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, unsigned count); + const Expr *expr, + const LocationContext *LCtx, + unsigned count); DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, QualType type, + const Expr *expr, + const LocationContext *LCtx, + QualType type, unsigned count); + + DefinedOrUnknownSVal getConjuredSymbolVal(const Stmt *stmt, + const LocationContext *LCtx, + QualType type, + unsigned visitCount); DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( SymbolRef parentSymbol, const TypedValueRegion *region); @@ -175,11 +223,13 @@ public: BasicVals.getValue(integer->getValue(), integer->getType()->isUnsignedIntegerOrEnumerationType())); } - - nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean) { - return makeTruthVal(boolean->getValue()); + + nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) { + return makeTruthVal(boolean->getValue(), boolean->getType()); } + nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean); + nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) { return nonloc::ConcreteInt(BasicVals.getValue(integer)); } @@ -220,9 +270,15 @@ public: NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType type); + NonLoc makeNonLoc(const llvm::APSInt& rhs, BinaryOperator::Opcode op, + const SymExpr *lhs, QualType type); + NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type); + /// \brief Create a NonLoc value for cast. + NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy); + nonloc::ConcreteInt makeTruthVal(bool b, QualType type) { return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type)); } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 5827b00..ed01db2 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -17,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "llvm/ADT/ImmutableList.h" //==------------------------------------------------------------------------==// @@ -121,50 +122,39 @@ public: /// Otherwise return 0. const FunctionDecl *getAsFunctionDecl() const; - /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and - /// wraps a symbol, return that SymbolRef. Otherwise return NULL. + /// If this SVal is a location (subclasses Loc) and + /// wraps a symbol, return that SymbolRef. Otherwise return 0. SymbolRef getAsLocSymbol() const; /// Get the symbol in the SVal or its base region. SymbolRef getLocSymbolInBase() const; - /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. - /// Otherwise return a SymbolRef where 'isValid()' returns false. + /// If this SVal wraps a symbol return that SymbolRef. + /// Otherwise, return 0. SymbolRef getAsSymbol() const; /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then /// return that expression. Otherwise return NULL. const SymExpr *getAsSymbolicExpression() const; + const SymExpr* getAsSymExpr() const; + const MemRegion *getAsRegion() const; void dumpToStream(raw_ostream &OS) const; void dump() const; - // Iterators. - class symbol_iterator { - SmallVector<const SymExpr*, 5> itr; - void expand(); - public: - symbol_iterator() {} - symbol_iterator(const SymExpr *SE); - - symbol_iterator &operator++(); - SymbolRef operator*(); - - bool operator==(const symbol_iterator &X) const; - bool operator!=(const symbol_iterator &X) const; - }; - - symbol_iterator symbol_begin() const { + SymExpr::symbol_iterator symbol_begin() const { const SymExpr *SE = getAsSymbolicExpression(); if (SE) - return symbol_iterator(SE); + return SE->symbol_begin(); else - return symbol_iterator(); + return SymExpr::symbol_iterator(); } - symbol_iterator symbol_end() const { return symbol_iterator(); } + SymExpr::symbol_iterator symbol_end() const { + return SymExpr::symbol_end(); + } // Implement isa<T> support. static inline bool classof(const SVal*) { return true; } @@ -274,43 +264,30 @@ namespace nonloc { enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind, LocAsIntegerKind, CompoundValKind, LazyCompoundValKind }; +/// \brief Represents symbolic expression. class SymbolVal : public NonLoc { public: SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} SymbolRef getSymbol() const { - return (const SymbolData*) Data; - } - - static inline bool classof(const SVal* V) { - return V->getBaseKind() == NonLocKind && - V->getSubKind() == SymbolValKind; - } - - static inline bool classof(const NonLoc* V) { - return V->getSubKind() == SymbolValKind; + return (const SymExpr*) Data; } -}; - -class SymExprVal : public NonLoc { -public: - explicit SymExprVal(const SymExpr *SE) - : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {} - const SymExpr *getSymbolicExpression() const { - return reinterpret_cast<const SymExpr*>(Data); + bool isExpression() { + return !isa<SymbolData>(getSymbol()); } static inline bool classof(const SVal* V) { return V->getBaseKind() == NonLocKind && - V->getSubKind() == SymExprValKind; + V->getSubKind() == SymbolValKind; } static inline bool classof(const NonLoc* V) { - return V->getSubKind() == SymExprValKind; + return V->getSubKind() == SymbolValKind; } }; +/// \brief Value representing integer constant. class ConcreteInt : public NonLoc { public: explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index a688d7f..5315f4b 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -29,6 +29,7 @@ class StackFrameContext; namespace ento { +class CallOrObjCMessage; class ProgramState; class ProgramStateManager; class SubRegionMap; @@ -54,7 +55,7 @@ public: /// expected type of the returned value. This is used if the value is /// lazily computed. /// \return The value bound to the location \c loc. - virtual SVal Retrieve(Store store, Loc loc, QualType T = QualType()) = 0; + virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0; /// Return a state with the specified value bound to the given location. /// \param[in] state The analysis state. @@ -93,18 +94,12 @@ public: return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC)); } - virtual Loc getLValueString(const StringLiteral* S) { - return svalBuilder.makeLoc(MRMgr.getStringRegion(S)); - } - Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL, const LocationContext *LC) { return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); } - virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base) { - return getLValueFieldOrIvar(decl, base); - } + virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base); virtual SVal getLValueField(const FieldDecl *D, SVal Base) { return getLValueFieldOrIvar(D, Base); @@ -114,7 +109,7 @@ public: // FIXME: This should soon be eliminated altogether; clients should deal with // region extents directly. - virtual DefinedOrUnknownSVal getSizeInElements(const ProgramState *state, + virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state, const MemRegion *region, QualType EleTy) { return UnknownVal(); @@ -125,17 +120,26 @@ public: virtual SVal ArrayToPointer(Loc Array) = 0; /// Evaluates DerivedToBase casts. - virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) { - return UnknownVal(); - } + virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) = 0; + + /// \brief Evaluates C++ dynamic_cast cast. + /// The callback may result in the following 3 scenarios: + /// - Successful cast (ex: derived is subclass of base). + /// - Failed cast (ex: derived is definitely not a subclass of base). + /// - We don't know (base is a symbolic region and we don't have + /// enough info to determine if the cast will succeed at run time). + /// The function returns an SVal representing the derived class; it's + /// valid only if Failed flag is set to false. + virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType, + bool &Failed) = 0; class CastResult { - const ProgramState *state; + ProgramStateRef state; const MemRegion *region; public: - const ProgramState *getState() const { return state; } + ProgramStateRef getState() const { return state; } const MemRegion* getRegion() const { return region; } - CastResult(const ProgramState *s, const MemRegion* r = 0) : state(s), region(r){} + CastResult(ProgramStateRef s, const MemRegion* r = 0) : state(s), region(r){} }; const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); @@ -180,8 +184,8 @@ public: /// symbols to mark the values of invalidated regions. /// \param[in,out] IS A set to fill with any symbols that are no longer /// accessible. Pass \c NULL if this information will not be used. - /// \param[in] invalidateGlobals If \c true, any non-static global regions - /// are invalidated as well. + /// \param[in] Call The call expression which will be used to determine which + /// globals should get invalidated. /// \param[in,out] Regions A vector to fill with any regions being /// invalidated. This should include any regions explicitly invalidated /// even if they do not currently have bindings. Pass \c NULL if this @@ -189,14 +193,16 @@ public: virtual StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned Count, + const LocationContext *LCtx, InvalidatedSymbols &IS, - bool invalidateGlobals, + const CallOrObjCMessage *Call, InvalidatedRegions *Invalidated) = 0; /// enterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. - virtual StoreRef enterStackFrame(const ProgramState *state, - const StackFrameContext *frame); + virtual StoreRef enterStackFrame(ProgramStateRef state, + const LocationContext *callerCtx, + const StackFrameContext *calleeCtx); virtual void print(Store store, raw_ostream &Out, const char* nl, const char *sep) = 0; @@ -208,6 +214,21 @@ public: const MemRegion *region, SVal val) = 0; }; + class FindUniqueBinding : + public BindingsHandler { + SymbolRef Sym; + const MemRegion* Binding; + bool First; + + public: + FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {} + + bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, + SVal val); + operator bool() { return First && Binding; } + const MemRegion *getRegion() { return Binding; } + }; + /// iterBindings - Iterate over the bindings in the Store. virtual void iterBindings(Store store, BindingsHandler& f) = 0; @@ -258,10 +279,12 @@ inline StoreRef &StoreRef::operator=(StoreRef const &newStore) { /// SubRegionMap - An abstract interface that represents a queryable map /// between MemRegion objects and their subregions. class SubRegionMap { + virtual void anchor(); public: virtual ~SubRegionMap() {} class Visitor { + virtual void anchor(); public: virtual ~Visitor() {} virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index ae212bc..baf57d4 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -26,27 +26,26 @@ class Stmt; namespace ento { -template <typename PP> class GenericNodeBuilder; +struct NodeBuilderContext; class AnalysisManager; class ExplodedNodeSet; class ExplodedNode; class ProgramState; class ProgramStateManager; class BlockCounter; -class StmtNodeBuilder; class BranchNodeBuilder; class IndirectGotoNodeBuilder; class SwitchNodeBuilder; class EndOfFunctionNodeBuilder; -class CallEnterNodeBuilder; -class CallExitNodeBuilder; +class NodeBuilderWithSinks; class MemRegion; class SubEngine { + virtual void anchor(); public: virtual ~SubEngine() {} - virtual const ProgramState *getInitialState(const LocationContext *InitLoc) = 0; + virtual ProgramStateRef getInitialState(const LocationContext *InitLoc) = 0; virtual AnalysisManager &getAnalysisManager() = 0; @@ -54,18 +53,23 @@ public: /// Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - virtual void processCFGElement(const CFGElement E, StmtNodeBuilder& builder)=0; + virtual void processCFGElement(const CFGElement E, ExplodedNode* Pred, + unsigned StmtIdx, NodeBuilderContext *Ctx)=0; /// Called by CoreEngine when it starts processing a CFGBlock. The /// SubEngine is expected to populate dstNodes with new nodes representing /// updated analysis state, or generate no nodes at all if it doesn't. - virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes, - GenericNodeBuilder<BlockEntrance> &nodeBuilder) = 0; + virtual void processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder) = 0; /// Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. virtual void processBranch(const Stmt *Condition, const Stmt *Term, - BranchNodeBuilder& builder) = 0; + NodeBuilderContext& BuilderCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) = 0; /// Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a computed goto jump. @@ -77,40 +81,41 @@ public: /// Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - virtual void processEndOfFunction(EndOfFunctionNodeBuilder& builder) = 0; + virtual void processEndOfFunction(NodeBuilderContext& BC) = 0; // Generate the entry node of the callee. - virtual void processCallEnter(CallEnterNodeBuilder &builder) = 0; + virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0; // Generate the first post callsite node. - virtual void processCallExit(CallExitNodeBuilder &builder) = 0; + virtual void processCallExit(ExplodedNode *Pred) = 0; /// Called by ConstraintManager. Used to call checker-specific /// logic for handling assumptions on symbolic values. - virtual const ProgramState *processAssume(const ProgramState *state, + virtual ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption) = 0; /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a /// region change should trigger a processRegionChanges update. - virtual bool wantsRegionChangeUpdate(const ProgramState *state) = 0; + virtual bool wantsRegionChangeUpdate(ProgramStateRef state) = 0; - /// processRegionChanges - Called by ProgramStateManager whenever a change is made - /// to the store. Used to update checkers that track region values. - virtual const ProgramState * - processRegionChanges(const ProgramState *state, + /// processRegionChanges - Called by ProgramStateManager whenever a change is + /// made to the store. Used to update checkers that track region values. + virtual ProgramStateRef + processRegionChanges(ProgramStateRef state, const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions) = 0; + ArrayRef<const MemRegion *> Regions, + const CallOrObjCMessage *Call) = 0; - inline const ProgramState * - processRegionChange(const ProgramState *state, + inline ProgramStateRef + processRegionChange(ProgramStateRef state, const MemRegion* MR) { - return processRegionChanges(state, 0, MR, MR); + return processRegionChanges(state, 0, MR, MR, 0); } /// printState - Called by ProgramStateManager to print checker-specific data. - virtual void printState(raw_ostream &Out, const ProgramState *State, + virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) = 0; /// Called by CoreEngine when the analysis worklist is either empty or the diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 0d6e18e..c7de7ef 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -40,13 +40,16 @@ namespace ento { class TypedValueRegion; class VarRegion; +/// \brief Symbolic value. These values used to capture symbolic execution of +/// the program. class SymExpr : public llvm::FoldingSetNode { + virtual void anchor(); public: enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, MetadataKind, BEGIN_SYMBOLS = RegionValueKind, END_SYMBOLS = MetadataKind, - SymIntKind, SymSymKind }; + SymIntKind, IntSymKind, SymSymKind, CastSymbolKind }; private: Kind K; @@ -58,21 +61,49 @@ public: Kind getKind() const { return K; } - void dump() const; + virtual void dump() const; - virtual void dumpToStream(raw_ostream &os) const = 0; + virtual void dumpToStream(raw_ostream &os) const {} virtual QualType getType(ASTContext&) const = 0; virtual void Profile(llvm::FoldingSetNodeID& profile) = 0; // Implement isa<T> support. static inline bool classof(const SymExpr*) { return true; } + + /// \brief Iterator over symbols that the current symbol depends on. + /// + /// For SymbolData, it's the symbol itself; for expressions, it's the + /// expression symbol and all the operands in it. Note, SymbolDerived is + /// treated as SymbolData - the iterator will NOT visit the parent region. + class symbol_iterator { + SmallVector<const SymExpr*, 5> itr; + void expand(); + public: + symbol_iterator() {} + symbol_iterator(const SymExpr *SE); + + symbol_iterator &operator++(); + const SymExpr* operator*(); + + bool operator==(const symbol_iterator &X) const; + bool operator!=(const symbol_iterator &X) const; + }; + + symbol_iterator symbol_begin() const { + return symbol_iterator(this); + } + static symbol_iterator symbol_end() { return symbol_iterator(); } }; -typedef unsigned SymbolID; +typedef const SymExpr* SymbolRef; +typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; +typedef unsigned SymbolID; +/// \brief A symbol representing data which can be stored in a memory location +/// (region). class SymbolData : public SymExpr { -private: + virtual void anchor(); const SymbolID Sym; protected: @@ -90,10 +121,7 @@ public: } }; -typedef const SymbolData* SymbolRef; -typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; - -/// A symbol representing the value of a MemRegion. +///\brief A symbol representing the value stored at a MemRegion. class SymbolRegionValue : public SymbolData { const TypedValueRegion *R; @@ -112,7 +140,7 @@ public: Profile(profile, R); } - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; QualType getType(ASTContext&) const; @@ -122,17 +150,21 @@ public: } }; -/// A symbol representing the result of an expression. +/// A symbol representing the result of an expression in the case when we do +/// not know anything about what the expression is. class SymbolConjured : public SymbolData { const Stmt *S; QualType T; unsigned Count; + const LocationContext *LCtx; const void *SymbolTag; public: - SymbolConjured(SymbolID sym, const Stmt *s, QualType t, unsigned count, + SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, + QualType t, unsigned count, const void *symbolTag) : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), + LCtx(lctx), SymbolTag(symbolTag) {} const Stmt *getStmt() const { return S; } @@ -141,19 +173,21 @@ public: QualType getType(ASTContext&) const; - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, - QualType T, unsigned Count, const void *SymbolTag) { + QualType T, unsigned Count, const LocationContext *LCtx, + const void *SymbolTag) { profile.AddInteger((unsigned) ConjuredKind); profile.AddPointer(S); + profile.AddPointer(LCtx); profile.Add(T); profile.AddInteger(Count); profile.AddPointer(SymbolTag); } virtual void Profile(llvm::FoldingSetNodeID& profile) { - Profile(profile, S, T, Count, SymbolTag); + Profile(profile, S, T, Count, LCtx, SymbolTag); } // Implement isa<T> support. @@ -177,7 +211,7 @@ public: QualType getType(ASTContext&) const; - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, const TypedValueRegion *r) { @@ -210,7 +244,7 @@ public: QualType getType(ASTContext&) const; - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { profile.AddInteger((unsigned) ExtentKind); @@ -249,7 +283,7 @@ public: QualType getType(ASTContext&) const; - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, const Stmt *S, QualType T, unsigned Count, @@ -272,6 +306,42 @@ public: } }; +/// \brief Represents a cast expression. +class SymbolCast : public SymExpr { + const SymExpr *Operand; + /// Type of the operand. + QualType FromTy; + /// The type of the result. + QualType ToTy; + +public: + SymbolCast(const SymExpr *In, QualType From, QualType To) : + SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } + + QualType getType(ASTContext &C) const { return ToTy; } + + const SymExpr *getOperand() const { return Operand; } + + virtual void dumpToStream(raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& ID, + const SymExpr *In, QualType From, QualType To) { + ID.AddInteger((unsigned) CastSymbolKind); + ID.AddPointer(In); + ID.Add(From); + ID.Add(To); + } + + void Profile(llvm::FoldingSetNodeID& ID) { + Profile(ID, Operand, FromTy, ToTy); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr *SE) { + return SE->getKind() == CastSymbolKind; + } +}; + /// SymIntExpr - Represents symbolic expression like 'x' + 3. class SymIntExpr : public SymExpr { const SymExpr *LHS; @@ -290,7 +360,7 @@ public: BinaryOperator::Opcode getOpcode() const { return Op; } - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; const SymExpr *getLHS() const { return LHS; } const llvm::APSInt &getRHS() const { return RHS; } @@ -315,6 +385,47 @@ public: } }; +/// IntSymExpr - Represents symbolic expression like 3 - 'x'. +class IntSymExpr : public SymExpr { + const llvm::APSInt& LHS; + BinaryOperator::Opcode Op; + const SymExpr *RHS; + QualType T; + +public: + IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, + const SymExpr *rhs, QualType t) + : SymExpr(IntSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} + + QualType getType(ASTContext &C) const { return T; } + + BinaryOperator::Opcode getOpcode() const { return Op; } + + virtual void dumpToStream(raw_ostream &os) const; + + const SymExpr *getRHS() const { return RHS; } + const llvm::APSInt &getLHS() const { return LHS; } + + static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, + QualType t) { + ID.AddInteger((unsigned) IntSymKind); + ID.AddPointer(&lhs); + ID.AddInteger(op); + ID.AddPointer(rhs); + ID.Add(t); + } + + void Profile(llvm::FoldingSetNodeID& ID) { + Profile(ID, LHS, Op, RHS, T); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr *SE) { + return SE->getKind() == IntSymKind; + } +}; + /// SymSymExpr - Represents symbolic expression like 'x' + 'y'. class SymSymExpr : public SymExpr { const SymExpr *LHS; @@ -335,7 +446,7 @@ public: // generation of virtual functions. QualType getType(ASTContext &C) const { return T; } - void dumpToStream(raw_ostream &os) const; + virtual void dumpToStream(raw_ostream &os) const; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { @@ -382,13 +493,18 @@ public: /// \brief Make a unique symbol for MemRegion R according to its kind. const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R); - const SymbolConjured* getConjuredSymbol(const Stmt *E, QualType T, + const SymbolConjured* getConjuredSymbol(const Stmt *E, + const LocationContext *LCtx, + QualType T, unsigned VisitCount, const void *SymbolTag = 0); - const SymbolConjured* getConjuredSymbol(const Expr *E, unsigned VisitCount, + const SymbolConjured* getConjuredSymbol(const Expr *E, + const LocationContext *LCtx, + unsigned VisitCount, const void *SymbolTag = 0) { - return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag); + return getConjuredSymbol(E, LCtx, E->getType(), + VisitCount, SymbolTag); } const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, @@ -404,6 +520,9 @@ public: QualType T, unsigned VisitCount, const void *SymbolTag = 0); + const SymbolCast* getCastSymbol(const SymExpr *Operand, + QualType From, QualType To); + const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t); @@ -412,6 +531,10 @@ public: return getSymIntExpr(&lhs, op, rhs, t); } + const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs, + BinaryOperator::Opcode op, + const SymExpr *rhs, QualType t); + const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t); @@ -464,7 +587,7 @@ public: bool isLive(SymbolRef sym); bool isLiveRegion(const MemRegion *region); - bool isLive(const Stmt *ExprVal) const; + bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const; bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const; /// \brief Unconditionally marks a symbol as live. @@ -537,7 +660,7 @@ public: namespace llvm { static inline raw_ostream &operator<<(raw_ostream &os, - const clang::ento::SymExpr *SE) { + const clang::ento::SymExpr *SE) { SE->dumpToStream(os); return os; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h new file mode 100644 index 0000000..53205d3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -0,0 +1,40 @@ +//== TaintManager.h - Managing taint --------------------------- -*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides APIs for adding, removing, querying symbol taint. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TAINTMANAGER_H +#define LLVM_CLANG_TAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" + +namespace clang { +namespace ento { + +/// The GDM component containing the tainted root symbols. We lazily infer the +/// taint of the dependent symbols. Currently, this is a map from a symbol to +/// tag kind. TODO: Should support multiple tag kinds. +struct TaintMap {}; +typedef llvm::ImmutableMap<SymbolRef, TaintTagType> TaintMapImpl; +template<> struct ProgramStateTrait<TaintMap> + : public ProgramStatePartialTrait<TaintMapImpl> { + static void *GDMIndex() { static int index = 0; return &index; } +}; + +class TaintManager { + + TaintManager() {} +}; + +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h new file mode 100644 index 0000000..8ddc8b9d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h @@ -0,0 +1,27 @@ +//== TaintTag.h - Path-sensitive "State" for tracking values -*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a set of taint tags. Several tags are used to differentiate kinds +// of taint. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_TAINTTAG_H +#define LLVM_CLANG_TAINTTAG_H + +namespace clang { +namespace ento { + +/// The type of taint, which helps to differentiate between different types of +/// taint. +typedef unsigned TaintTagType; +static const TaintTagType TaintTagGeneric = 0; + +}} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index fa34075..51aa753 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -73,6 +73,7 @@ public: } void enqueue(ExplodedNode *N) { + assert(N->getLocation().getKind() != ProgramPoint::PostStmtKind); enqueue(WorkListUnit(N, CurrentCounter)); } diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h new file mode 100644 index 0000000..3430320 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h @@ -0,0 +1,164 @@ +//===--- CompilationDatabase.h - --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an interface and multiple implementations for +// CompilationDatabases. +// +// While C++ refactoring and analysis tools are not compilers, and thus +// don't run as part of the build system, they need the exact information +// of a build in order to be able to correctly understand the C++ code of +// the project. This information is provided via the CompilationDatabase +// interface. +// +// To create a CompilationDatabase from a build directory one can call +// CompilationDatabase::loadFromDirectory(), which deduces the correct +// compilation database from the root of the build tree. +// +// See the concrete subclasses of CompilationDatabase for currently supported +// formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H +#define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include <string> +#include <vector> + +namespace llvm { +class MemoryBuffer; +} // end namespace llvm + +namespace clang { +namespace tooling { + +/// \brief Specifies the working directory and command of a compilation. +struct CompileCommand { + CompileCommand() {} + CompileCommand(StringRef Directory, ArrayRef<std::string> CommandLine) + : Directory(Directory), CommandLine(CommandLine) {} + + /// \brief The working directory the command was executed from. + std::string Directory; + + /// \brief The command line that was executed. + std::vector<std::string> CommandLine; +}; + +/// \brief Interface for compilation databases. +/// +/// A compilation database allows the user to retrieve all compile command lines +/// that a specified file is compiled with in a project. +/// The retrieved compile command lines can be used to run clang tools over +/// a subset of the files in a project. +class CompilationDatabase { +public: + virtual ~CompilationDatabase(); + + /// \brief Loads a compilation database from a build directory. + /// + /// Looks at the specified 'BuildDirectory' and creates a compilation database + /// that allows to query compile commands for source files in the + /// corresponding source tree. + /// + /// Returns NULL and sets ErrorMessage if we were not able to build up a + /// compilation database for the build directory. + /// + /// FIXME: Currently only supports JSON compilation databases, which + /// are named 'compile_commands.json' in the given directory. Extend this + /// for other build types (like ninja build files). + static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory, + std::string &ErrorMessage); + + /// \brief Returns all compile commands in which the specified file was + /// compiled. + /// + /// This includes compile comamnds that span multiple source files. + /// For example, consider a project with the following compilations: + /// $ clang++ -o test a.cc b.cc t.cc + /// $ clang++ -o production a.cc b.cc -DPRODUCTION + /// A compilation database representing the project would return both command + /// lines for a.cc and b.cc and only the first command line for t.cc. + virtual std::vector<CompileCommand> getCompileCommands( + StringRef FilePath) const = 0; +}; + +/// \brief A JSON based compilation database. +/// +/// JSON compilation database files must contain a list of JSON objects which +/// provide the command lines in the attributes 'directory', 'command' and +/// 'file': +/// [ +/// { "directory": "<working directory of the compile>", +/// "command": "<compile command line>", +/// "file": "<path to source file>" +/// }, +/// ... +/// ] +/// Each object entry defines one compile action. The specified file is +/// considered to be the main source file for the translation unit. +/// +/// JSON compilation databases can for example be generated in CMake projects +/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS. +class JSONCompilationDatabase : public CompilationDatabase { +public: + + /// \brief Loads a JSON compilation database from the specified file. + /// + /// Returns NULL and sets ErrorMessage if the database could not be + /// loaded from the given file. + static JSONCompilationDatabase *loadFromFile(StringRef FilePath, + std::string &ErrorMessage); + + /// \brief Loads a JSON compilation database from a data buffer. + /// + /// Returns NULL and sets ErrorMessage if the database could not be loaded. + static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString, + std::string &ErrorMessage); + + /// \brief Returns all compile comamnds in which the specified file was + /// compiled. + /// + /// FIXME: Currently FilePath must be an absolute path inside the + /// source directory which does not have symlinks resolved. + virtual std::vector<CompileCommand> getCompileCommands( + StringRef FilePath) const; + +private: + /// \brief Constructs a JSON compilation database on a memory buffer. + JSONCompilationDatabase(llvm::MemoryBuffer *Database) + : Database(Database) {} + + /// \brief Parses the database file and creates the index. + /// + /// Returns whether parsing succeeded. Sets ErrorMessage if parsing + /// failed. + bool parse(std::string &ErrorMessage); + + // Tuple (directory, commandline) where 'commandline' is a JSON escaped bash + // escaped command line. + typedef std::pair<StringRef, StringRef> CompileCommandRef; + + // Maps file paths to the compile command lines for that file. + llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile; + + llvm::OwningPtr<llvm::MemoryBuffer> Database; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H + diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h new file mode 100644 index 0000000..868eae3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h @@ -0,0 +1,213 @@ +//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements functions to run clang tools standalone instead +// of running them as a plugin. +// +// A ClangTool is initialized with a CompilationDatabase and a set of files +// to run over. The tool will then run a user-specified FrontendAction over +// all TUs in which the given files are compiled. +// +// It is also possible to run a FrontendAction over a snippet of code by +// calling runSyntaxOnlyToolOnCode, which is useful for unit testing. +// +// Applications that need more fine grained control over how to run +// multiple FrontendActions over code can use ToolInvocation. +// +// Example tools: +// - running clang -fsyntax-only over source code from an editor to get +// fast syntax checks +// - running match/replace tools over C++ code +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TOOLING_H +#define LLVM_CLANG_TOOLING_TOOLING_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Driver/Util.h" +#include <string> +#include <vector> + +namespace clang { + +namespace driver { +class Compilation; +} // end namespace driver + +class CompilerInvocation; +class SourceManager; +class FrontendAction; + +namespace tooling { + +class CompilationDatabase; + +/// \brief Interface to generate clang::FrontendActions. +class FrontendActionFactory { +public: + virtual ~FrontendActionFactory(); + + /// \brief Returns a new clang::FrontendAction. + /// + /// The caller takes ownership of the returned action. + virtual clang::FrontendAction *create() = 0; +}; + +/// \brief Returns a new FrontendActionFactory for a given type. +/// +/// T must extend clang::FrontendAction. +/// +/// Example: +/// FrontendActionFactory *Factory = +/// newFrontendActionFactory<clang::SyntaxOnlyAction>(); +template <typename T> +FrontendActionFactory *newFrontendActionFactory(); + +/// \brief Returns a new FrontendActionFactory for any type that provides an +/// implementation of newFrontendAction(). +/// +/// FactoryT must implement: FrontendAction *newFrontendAction(). +/// +/// Example: +/// struct ProvidesFrontendActions { +/// FrontendAction *newFrontendAction(); +/// } Factory; +/// FrontendActionFactory *FactoryAdapter = +/// newFrontendActionFactory(&Factory); +template <typename FactoryT> +FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory); + +/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// \param FileName The file name which 'Code' will be mapped as. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, + const Twine &FileName = "input.cc"); + +/// \brief Utility to run a FrontendAction in a single clang invocation. +class ToolInvocation { + public: + /// \brief Create a tool invocation. + /// + /// \param CommandLine The command line arguments to clang. + /// \param ToolAction The action to be executed. Class takes ownership. + /// \param Files The FileManager used for the execution. Class does not take + /// ownership. + ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *ToolAction, + FileManager *Files); + + /// \brief Map a virtual file to be used while running the tool. + /// + /// \param FilePath The path at which the content will be mapped. + /// \param Content A null terminated buffer of the file's content. + void mapVirtualFile(StringRef FilePath, StringRef Content); + + /// \brief Run the clang invocation. + /// + /// \returns True if there were no errors during execution. + bool run(); + + private: + void addFileMappingsTo(SourceManager &SourceManager); + + bool runInvocation(const char *BinaryName, + clang::driver::Compilation *Compilation, + clang::CompilerInvocation *Invocation, + const clang::driver::ArgStringList &CC1Args, + clang::FrontendAction *ToolAction); + + std::vector<std::string> CommandLine; + llvm::OwningPtr<FrontendAction> ToolAction; + FileManager *Files; + // Maps <file name> -> <file content>. + llvm::StringMap<StringRef> MappedFileContents; +}; + +/// \brief Utility to run a FrontendAction over a set of files. +/// +/// This class is written to be usable for command line utilities. +class ClangTool { + public: + /// \brief Constructs a clang tool to run over a list of files. + /// + /// \param Compilations The CompilationDatabase which contains the compile + /// command lines for the given source paths. + /// \param SourcePaths The source files to run over. If a source files is + /// not found in Compilations, it is skipped. + ClangTool(const CompilationDatabase &Compilations, + ArrayRef<std::string> SourcePaths); + + /// \brief Map a virtual file to be used while running the tool. + /// + /// \param FilePath The path at which the content will be mapped. + /// \param Content A null terminated buffer of the file's content. + void mapVirtualFile(StringRef FilePath, StringRef Content); + + /// Runs a frontend action over all files specified in the command line. + /// + /// \param ActionFactory Factory generating the frontend actions. The function + /// takes ownership of this parameter. A new action is generated for every + /// processed translation unit. + int run(FrontendActionFactory *ActionFactory); + + /// \brief Returns the file manager used in the tool. + /// + /// The file manager is shared between all translation units. + FileManager &getFiles() { return Files; } + + private: + // We store command lines as pair (file name, command line). + typedef std::pair< std::string, std::vector<std::string> > CommandLine; + std::vector<CommandLine> CommandLines; + + FileManager Files; + // Contains a list of pairs (<file name>, <file content>). + std::vector< std::pair<StringRef, StringRef> > MappedFileContents; +}; + +template <typename T> +FrontendActionFactory *newFrontendActionFactory() { + class SimpleFrontendActionFactory : public FrontendActionFactory { + public: + virtual clang::FrontendAction *create() { return new T; } + }; + + return new SimpleFrontendActionFactory; +} + +template <typename FactoryT> +FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory) { + class FrontendActionFactoryAdapter : public FrontendActionFactory { + public: + explicit FrontendActionFactoryAdapter(FactoryT *ActionFactory) + : ActionFactory(ActionFactory) {} + + virtual clang::FrontendAction *create() { + return ActionFactory->newFrontendAction(); + } + + private: + FactoryT *ActionFactory; + }; + + return new FrontendActionFactoryAdapter(ActionFactory); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLING_H + |