diff options
Diffstat (limited to 'contrib/llvm/tools/clang/include')
271 files changed, 80509 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/include/CMakeLists.txt b/contrib/llvm/tools/clang/include/CMakeLists.txt new file mode 100644 index 0000000..253a09b --- /dev/null +++ b/contrib/llvm/tools/clang/include/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(clang) diff --git a/contrib/llvm/tools/clang/include/Makefile b/contrib/llvm/tools/clang/include/Makefile new file mode 100644 index 0000000..f686d6a --- /dev/null +++ b/contrib/llvm/tools/clang/include/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../.. +DIRS := clang clang-c + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h new file mode 100644 index 0000000..86926bd --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -0,0 +1,2012 @@ +/*===-- clang-c/Index.h - Indexing Public C Interface -------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a public inferface to a Clang library for extracting *| +|* high-level symbol information from source files without exposing the full *| +|* Clang C++ API. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef CLANG_C_INDEX_H +#define CLANG_C_INDEX_H + +#include <sys/stat.h> +#include <time.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* MSVC DLL import/export. */ +#ifdef _MSC_VER + #ifdef _CINDEX_LIB_ + #define CINDEX_LINKAGE __declspec(dllexport) + #else + #define CINDEX_LINKAGE __declspec(dllimport) + #endif +#else + #define CINDEX_LINKAGE +#endif + +/** \defgroup CINDEX C Interface to Clang + * + * The C Interface to Clang provides a relatively small API that exposes + * facilities for parsing source code into an abstract syntax tree (AST), + * loading already-parsed ASTs, traversing the AST, associating + * physical source locations with elements within the AST, and other + * facilities that support Clang-based development tools. + * + * This C interface to Clang will never provide all of the information + * representation stored in Clang's C++ AST, nor should it: the intent is to + * maintain an API that is relatively stable from one release to the next, + * providing only the basic functionality needed to support development tools. + * + * To avoid namespace pollution, data types are prefixed with "CX" and + * functions are prefixed with "clang_". + * + * @{ + */ + +/** + * \brief An "index" that consists of a set of translation units that would + * typically be linked together into an executable or library. + */ +typedef void *CXIndex; + +/** + * \brief A single translation unit, which resides in an index. + */ +typedef void *CXTranslationUnit; /* A translation unit instance. */ + +/** + * \brief Opaque pointer representing client data that will be passed through + * to various callbacks and visitors. + */ +typedef void *CXClientData; + +/** + * \brief Provides the contents of a file that has not yet been saved to disk. + * + * Each CXUnsavedFile instance provides the name of a file on the + * system along with the current contents of that file that have not + * yet been saved to disk. + */ +struct CXUnsavedFile { + /** + * \brief The file whose contents have not yet been saved. + * + * This file must already exist in the file system. + */ + const char *Filename; + + /** + * \brief A buffer containing the unsaved contents of this file. + */ + const char *Contents; + + /** + * \brief The length of the unsaved contents of this buffer. + */ + unsigned long Length; +}; + +/** + * \defgroup CINDEX_STRING String manipulation routines + * + * @{ + */ + +/** + * \brief A character string. + * + * The \c CXString type is used to return strings from the interface when + * the ownership of that string might different from one call to the next. + * Use \c clang_getCString() to retrieve the string data and, once finished + * with the string data, call \c clang_disposeString() to free the string. + */ +typedef struct { + const char *Spelling; + /* A 1 value indicates the clang_ indexing API needed to allocate the string + (and it must be freed by clang_disposeString()). */ + int MustFreeString; +} CXString; + +/** + * \brief Retrieve the character data associated with the given string. + */ +CINDEX_LINKAGE const char *clang_getCString(CXString string); + +/** + * \brief Free the given string, + */ +CINDEX_LINKAGE void clang_disposeString(CXString string); + +/** + * @} + */ + +/** + * \brief clang_createIndex() provides a shared context for creating + * translation units. It provides two options: + * + * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" + * declarations (when loading any new translation units). A "local" declaration + * is one that belongs in the translation unit itself and not in a precompiled + * header that was used by the translation unit. If zero, all declarations + * will be enumerated. + * + * Here is an example: + * + * // excludeDeclsFromPCH = 1, displayDiagnostics=1 + * Idx = clang_createIndex(1, 1); + * + * // IndexTest.pch was produced with the following command: + * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" + * TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); + * + * // This will load all the symbols from 'IndexTest.pch' + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * // This will load all the symbols from 'IndexTest.c', excluding symbols + * // from 'IndexTest.pch'. + * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" }; + * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args, + * 0, 0); + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * This process of creating the 'pch', loading it separately, and using it (via + * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks + * (which gives the indexer the same performance benefit as the compiler). + */ +CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics); + +/** + * \brief Destroy the given index. + * + * The index must not be destroyed until all of the translation units created + * within that index have been destroyed. + */ +CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); + +/** + * \brief Request that AST's be generated externally for API calls which parse + * source code on the fly, e.g. \see createTranslationUnitFromSourceFile. + * + * Note: This is for debugging purposes only, and may be removed at a later + * date. + * + * \param index - The index to update. + * \param value - The new flag value. + */ +CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index, + int value); +/** + * \defgroup CINDEX_FILES File manipulation routines + * + * @{ + */ + +/** + * \brief A particular source file that is part of a translation unit. + */ +typedef void *CXFile; + + +/** + * \brief Retrieve the complete file and path name of the given file. + */ +CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile); + +/** + * \brief Retrieve the last modification time of the given file. + */ +CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile); + +/** + * \brief Retrieve a file handle within the given translation unit. + * + * \param tu the translation unit + * + * \param file_name the name of the file. + * + * \returns the file handle for the named file in the translation unit \p tu, + * or a NULL file handle if the file was not a part of this translation unit. + */ +CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu, + const char *file_name); + +/** + * @} + */ + +/** + * \defgroup CINDEX_LOCATIONS Physical source locations + * + * Clang represents physical source locations in its abstract syntax tree in + * great detail, with file, line, and column information for the majority of + * the tokens parsed in the source code. These data types and functions are + * used to represent source location information, either for a particular + * point in the program or for a range of points in the program, and extract + * specific location information from those data types. + * + * @{ + */ + +/** + * \brief Identifies a specific source location within a translation + * unit. + * + * Use clang_getInstantiationLocation() to map a source location to a + * particular file, line, and column. + */ +typedef struct { + void *ptr_data[2]; + unsigned int_data; +} CXSourceLocation; + +/** + * \brief Identifies a half-open character range in the source code. + * + * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the + * starting and end locations from a source range, respectively. + */ +typedef struct { + void *ptr_data[2]; + unsigned begin_int_data; + unsigned end_int_data; +} CXSourceRange; + +/** + * \brief Retrieve a NULL (invalid) source location. + */ +CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(); + +/** + * \determine Determine whether two source locations, which must refer into + * the same translation unit, refer to exactly the same point in the source + * code. + * + * \returns non-zero if the source locations refer to the same location, zero + * if they refer to different locations. + */ +CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1, + CXSourceLocation loc2); + +/** + * \brief Retrieves the source location associated with a given file/line/column + * in a particular translation unit. + */ +CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu, + CXFile file, + unsigned line, + unsigned column); + +/** + * \brief Retrieve a NULL (invalid) source range. + */ +CINDEX_LINKAGE CXSourceRange clang_getNullRange(); + +/** + * \brief Retrieve a source range given the beginning and ending source + * locations. + */ +CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin, + CXSourceLocation end); + +/** + * \brief Retrieve the file, line, column, and offset represented by + * the given source location. + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param file [out] if non-NULL, will be set to the file to which the given + * source location points. + * + * \param line [out] if non-NULL, will be set to the line to which the given + * source location points. + * + * \param column [out] if non-NULL, will be set to the column to which the given + * source location points. + * + * \param offset [out] if non-NULL, will be set to the offset into the + * buffer to which the given source location points. + */ +CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset); + +/** + * \brief Retrieve a source location representing the first character within a + * source range. + */ +CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range); + +/** + * \brief Retrieve a source location representing the last character within a + * source range. + */ +CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); + +/** + * \brief Determine if the source location occurs within the main file + * of the translation unit (as opposed to an included header). + */ +CINDEX_LINKAGE unsigned clang_isFromMainFile(CXSourceLocation loc); + +/** + * @} + */ + +/** + * \defgroup CINDEX_DIAG Diagnostic reporting + * + * @{ + */ + +/** + * \brief Describes the severity of a particular diagnostic. + */ +enum CXDiagnosticSeverity { + /** + * \brief A diagnostic that has been suppressed, e.g., by a command-line + * option. + */ + CXDiagnostic_Ignored = 0, + + /** + * \brief This diagnostic is a note that should be attached to the + * previous (non-note) diagnostic. + */ + CXDiagnostic_Note = 1, + + /** + * \brief This diagnostic indicates suspicious code that may not be + * wrong. + */ + CXDiagnostic_Warning = 2, + + /** + * \brief This diagnostic indicates that the code is ill-formed. + */ + CXDiagnostic_Error = 3, + + /** + * \brief This diagnostic indicates that the code is ill-formed such + * that future parser recovery is unlikely to produce useful + * results. + */ + CXDiagnostic_Fatal = 4 +}; + +/** + * \brief A single diagnostic, containing the diagnostic's severity, + * location, text, source ranges, and fix-it hints. + */ +typedef void *CXDiagnostic; + +/** + * \brief Determine the number of diagnostics produced for the given + * translation unit. + */ +CINDEX_LINKAGE unsigned clang_getNumDiagnostics(CXTranslationUnit Unit); + +/** + * \brief Retrieve a diagnostic associated with the given translation unit. + * + * \param Unit the translation unit to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, + unsigned Index); + +/** + * \brief Destroy a diagnostic. + */ +CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); + +/** + * \brief Options to control the display of diagnostics. + * + * The values in this enum are meant to be combined to customize the + * behavior of \c clang_displayDiagnostic(). + */ +enum CXDiagnosticDisplayOptions { + /** + * \brief Display the source-location information where the + * diagnostic was located. + * + * When set, diagnostics will be prefixed by the file, line, and + * (optionally) column to which the diagnostic refers. For example, + * + * \code + * test.c:28: warning: extra tokens at end of #endif directive + * \endcode + * + * This option corresponds to the clang flag \c -fshow-source-location. + */ + CXDiagnostic_DisplaySourceLocation = 0x01, + + /** + * \brief If displaying the source-location information of the + * diagnostic, also include the column number. + * + * This option corresponds to the clang flag \c -fshow-column. + */ + CXDiagnostic_DisplayColumn = 0x02, + + /** + * \brief If displaying the source-location information of the + * diagnostic, also include information about source ranges in a + * machine-parsable format. + * + * This option corresponds to the clang flag + * \c -fdiagnostics-print-source-range-info. + */ + CXDiagnostic_DisplaySourceRanges = 0x04 +}; + +/** + * \brief Format the given diagnostic in a manner that is suitable for display. + * + * This routine will format the given diagnostic to a string, rendering + * the diagnostic according to the various options given. The + * \c clang_defaultDiagnosticDisplayOptions() function returns the set of + * options that most closely mimics the behavior of the clang compiler. + * + * \param Diagnostic The diagnostic to print. + * + * \param Options A set of options that control the diagnostic display, + * created by combining \c CXDiagnosticDisplayOptions values. + * + * \returns A new string containing for formatted diagnostic. + */ +CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, + unsigned Options); + +/** + * \brief Retrieve the set of display options most similar to the + * default behavior of the clang compiler. + * + * \returns A set of display options suitable for use with \c + * clang_displayDiagnostic(). + */ +CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); + +/** + * \brief Print a diagnostic to the given file. + */ + +/** + * \brief Determine the severity of the given diagnostic. + */ +CINDEX_LINKAGE enum CXDiagnosticSeverity +clang_getDiagnosticSeverity(CXDiagnostic); + +/** + * \brief Retrieve the source location of the given diagnostic. + * + * This location is where Clang would print the caret ('^') when + * displaying the diagnostic on the command line. + */ +CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic); + +/** + * \brief Retrieve the text of the given diagnostic. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic); + +/** + * \brief Determine the number of source ranges associated with the given + * diagnostic. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic); + +/** + * \brief Retrieve a source range associated with the diagnostic. + * + * A diagnostic's source ranges highlight important elements in the source + * code. On the command line, Clang displays source ranges by + * underlining them with '~' characters. + * + * \param Diagnostic the diagnostic whose range is being extracted. + * + * \param Range the zero-based index specifying which range to + * + * \returns the requested source range. + */ +CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, + unsigned Range); + +/** + * \brief Determine the number of fix-it hints associated with the + * given diagnostic. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); + +/** + * \brief Retrieve the replacement information for a given fix-it. + * + * Fix-its are described in terms of a source range whose contents + * should be replaced by a string. This approach generalizes over + * three kinds of operations: removal of source code (the range covers + * the code to be removed and the replacement string is empty), + * replacement of source code (the range covers the code to be + * replaced and the replacement string provides the new code), and + * insertion (both the start and end of the range point at the + * insertion location, and the replacement string provides the text to + * insert). + * + * \param Diagnostic The diagnostic whose fix-its are being queried. + * + * \param FixIt The zero-based index of the fix-it. + * + * \param ReplacementRange The source range whose contents will be + * replaced with the returned replacement string. Note that source + * ranges are half-open ranges [a, b), so the source code should be + * replaced from a and up to (but not including) b. + * + * \returns A string containing text that should be replace the source + * code indicated by the \c ReplacementRange. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, + unsigned FixIt, + CXSourceRange *ReplacementRange); + +/** + * @} + */ + +/** + * \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation + * + * The routines in this group provide the ability to create and destroy + * translation units from files, either by parsing the contents of the files or + * by reading in a serialized representation of a translation unit. + * + * @{ + */ + +/** + * \brief Get the original translation unit source file name. + */ +CINDEX_LINKAGE CXString +clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); + +/** + * \brief Return the CXTranslationUnit for a given source file and the provided + * command line arguments one would pass to the compiler. + * + * Note: The 'source_filename' argument is optional. If the caller provides a + * NULL pointer, the name of the source file is expected to reside in the + * specified command line arguments. + * + * Note: When encountered in 'clang_command_line_args', the following options + * are ignored: + * + * '-c' + * '-emit-ast' + * '-fsyntax-only' + * '-o <output file>' (both '-o' and '<output file>' are ignored) + * + * + * \param source_filename - The name of the source file to load, or NULL if the + * source file is included in clang_command_line_args. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for code completion, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param diag_callback callback function that will receive any diagnostics + * emitted while processing this source file. If NULL, diagnostics will be + * suppressed. + * + * \param diag_client_data client data that will be passed to the diagnostic + * callback function. + */ +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, + const char *source_filename, + int num_clang_command_line_args, + const char **clang_command_line_args, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files); + +/** + * \brief Create a translation unit from an AST file (-emit-ast). + */ +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, + const char *ast_filename); + +/** + * \brief Destroy the specified CXTranslationUnit object. + */ +CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); + +/** + * @} + */ + +/** + * \brief Describes the kind of entity that a cursor refers to. + */ +enum CXCursorKind { + /* Declarations */ + /** + * \brief A declaration whose specific kind is not exposed via this + * interface. + * + * Unexposed declarations have the same operations as any other kind + * of declaration; one can extract their location information, + * spelling, find their definitions, etc. However, the specific kind + * of the declaration is not reported. + */ + CXCursor_UnexposedDecl = 1, + /** \brief A C or C++ struct. */ + CXCursor_StructDecl = 2, + /** \brief A C or C++ union. */ + CXCursor_UnionDecl = 3, + /** \brief A C++ class. */ + CXCursor_ClassDecl = 4, + /** \brief An enumeration. */ + CXCursor_EnumDecl = 5, + /** + * \brief A field (in C) or non-static data member (in C++) in a + * struct, union, or C++ class. + */ + CXCursor_FieldDecl = 6, + /** \brief An enumerator constant. */ + CXCursor_EnumConstantDecl = 7, + /** \brief A function. */ + CXCursor_FunctionDecl = 8, + /** \brief A variable. */ + CXCursor_VarDecl = 9, + /** \brief A function or method parameter. */ + CXCursor_ParmDecl = 10, + /** \brief An Objective-C @interface. */ + CXCursor_ObjCInterfaceDecl = 11, + /** \brief An Objective-C @interface for a category. */ + CXCursor_ObjCCategoryDecl = 12, + /** \brief An Objective-C @protocol declaration. */ + CXCursor_ObjCProtocolDecl = 13, + /** \brief An Objective-C @property declaration. */ + CXCursor_ObjCPropertyDecl = 14, + /** \brief An Objective-C instance variable. */ + CXCursor_ObjCIvarDecl = 15, + /** \brief An Objective-C instance method. */ + CXCursor_ObjCInstanceMethodDecl = 16, + /** \brief An Objective-C class method. */ + CXCursor_ObjCClassMethodDecl = 17, + /** \brief An Objective-C @implementation. */ + CXCursor_ObjCImplementationDecl = 18, + /** \brief An Objective-C @implementation for a category. */ + CXCursor_ObjCCategoryImplDecl = 19, + /** \brief A typedef */ + CXCursor_TypedefDecl = 20, + /** \brief A C++ class method. */ + CXCursor_CXXMethod = 21, + /** \brief A C++ namespace. */ + CXCursor_Namespace = 22, + /** \brief A linkage specification, e.g. 'extern "C"'. */ + CXCursor_LinkageSpec = 23, + + CXCursor_FirstDecl = CXCursor_UnexposedDecl, + CXCursor_LastDecl = CXCursor_LinkageSpec, + + /* References */ + CXCursor_FirstRef = 40, /* Decl references */ + CXCursor_ObjCSuperClassRef = 40, + CXCursor_ObjCProtocolRef = 41, + CXCursor_ObjCClassRef = 42, + /** + * \brief A reference to a type declaration. + * + * A type reference occurs anywhere where a type is named but not + * declared. For example, given: + * + * \code + * typedef unsigned size_type; + * size_type size; + * \endcode + * + * The typedef is a declaration of size_type (CXCursor_TypedefDecl), + * while the type of the variable "size" is referenced. The cursor + * referenced by the type of size is the typedef for size_type. + */ + CXCursor_TypeRef = 43, + CXCursor_LastRef = 43, + + /* Error conditions */ + CXCursor_FirstInvalid = 70, + CXCursor_InvalidFile = 70, + CXCursor_NoDeclFound = 71, + CXCursor_NotImplemented = 72, + CXCursor_InvalidCode = 73, + CXCursor_LastInvalid = CXCursor_InvalidCode, + + /* Expressions */ + CXCursor_FirstExpr = 100, + + /** + * \brief An expression whose specific kind is not exposed via this + * interface. + * + * Unexposed expressions have the same operations as any other kind + * of expression; one can extract their location information, + * spelling, children, etc. However, the specific kind of the + * expression is not reported. + */ + CXCursor_UnexposedExpr = 100, + + /** + * \brief An expression that refers to some value declaration, such + * as a function, varible, or enumerator. + */ + CXCursor_DeclRefExpr = 101, + + /** + * \brief An expression that refers to a member of a struct, union, + * class, Objective-C class, etc. + */ + CXCursor_MemberRefExpr = 102, + + /** \brief An expression that calls a function. */ + CXCursor_CallExpr = 103, + + /** \brief An expression that sends a message to an Objective-C + object or class. */ + CXCursor_ObjCMessageExpr = 104, + + /** \brief An expression that represents a block literal. */ + CXCursor_BlockExpr = 105, + + CXCursor_LastExpr = 105, + + /* Statements */ + CXCursor_FirstStmt = 200, + /** + * \brief A statement whose specific kind is not exposed via this + * interface. + * + * Unexposed statements have the same operations as any other kind of + * statement; one can extract their location information, spelling, + * children, etc. However, the specific kind of the statement is not + * reported. + */ + CXCursor_UnexposedStmt = 200, + CXCursor_LastStmt = 200, + + /** + * \brief Cursor that represents the translation unit itself. + * + * The translation unit cursor exists primarily to act as the root + * cursor for traversing the contents of a translation unit. + */ + CXCursor_TranslationUnit = 300, + + /* Attributes */ + CXCursor_FirstAttr = 400, + /** + * \brief An attribute whose specific kind is not exposed via this + * interface. + */ + CXCursor_UnexposedAttr = 400, + + CXCursor_IBActionAttr = 401, + CXCursor_IBOutletAttr = 402, + CXCursor_IBOutletCollectionAttr = 403, + CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr, + + /* Preprocessing */ + CXCursor_PreprocessingDirective = 500, + CXCursor_MacroDefinition = 501, + CXCursor_MacroInstantiation = 502, + CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective, + CXCursor_LastPreprocessing = CXCursor_MacroInstantiation +}; + +/** + * \brief A cursor representing some element in the abstract syntax tree for + * a translation unit. + * + * The cursor abstraction unifies the different kinds of entities in a + * program--declaration, statements, expressions, references to declarations, + * etc.--under a single "cursor" abstraction with a common set of operations. + * Common operation for a cursor include: getting the physical location in + * a source file where the cursor points, getting the name associated with a + * cursor, and retrieving cursors for any child nodes of a particular cursor. + * + * Cursors can be produced in two specific ways. + * clang_getTranslationUnitCursor() produces a cursor for a translation unit, + * from which one can use clang_visitChildren() to explore the rest of the + * translation unit. clang_getCursor() maps from a physical source location + * to the entity that resides at that location, allowing one to map from the + * source code into the AST. + */ +typedef struct { + enum CXCursorKind kind; + void *data[3]; +} CXCursor; + +/** + * \defgroup CINDEX_CURSOR_MANIP Cursor manipulations + * + * @{ + */ + +/** + * \brief Retrieve the NULL cursor, which represents no entity. + */ +CINDEX_LINKAGE CXCursor clang_getNullCursor(void); + +/** + * \brief Retrieve the cursor that represents the given translation unit. + * + * The translation unit cursor can be used to start traversing the + * various declarations within the given translation unit. + */ +CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit); + +/** + * \brief Determine whether two cursors are equivalent. + */ +CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor); + +/** + * \brief Retrieve the kind of the given cursor. + */ +CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor); + +/** + * \brief Determine whether the given cursor kind represents a declaration. + */ +CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind); + +/** + * \brief Determine whether the given cursor kind represents a simple + * reference. + * + * Note that other kinds of cursors (such as expressions) can also refer to + * other cursors. Use clang_getCursorReferenced() to determine whether a + * particular cursor refers to another entity. + */ +CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind); + +/** + * \brief Determine whether the given cursor kind represents an expression. + */ +CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind); + +/** + * \brief Determine whether the given cursor kind represents a statement. + */ +CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind); + +/** + * \brief Determine whether the given cursor kind represents an invalid + * cursor. + */ +CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); + +/** + * \brief Determine whether the given cursor kind represents a translation + * unit. + */ +CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind); + +/*** + * \brief Determine whether the given cursor represents a preprocessing + * element, such as a preprocessor directive or macro instantiation. + */ +CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind); + +/*** + * \brief Determine whether the given cursor represents a currently + * unexposed piece of the AST (e.g., CXCursor_UnexposedStmt). + */ +CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind); + +/** + * \brief Describe the linkage of the entity referred to by a cursor. + */ +enum CXLinkageKind { + /** \brief This value indicates that no linkage information is available + * for a provided CXCursor. */ + CXLinkage_Invalid, + /** + * \brief This is the linkage for variables, parameters, and so on that + * have automatic storage. This covers normal (non-extern) local variables. + */ + CXLinkage_NoLinkage, + /** \brief This is the linkage for static variables and static functions. */ + CXLinkage_Internal, + /** \brief This is the linkage for entities with external linkage that live + * in C++ anonymous namespaces.*/ + CXLinkage_UniqueExternal, + /** \brief This is the linkage for entities with true, external linkage. */ + CXLinkage_External +}; + +/** + * \brief Determine the linkage of the entity referred to by a given cursor. + */ +CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor); + +/** + * \brief Describe the "language" of the entity referred to by a cursor. + */ +CINDEX_LINKAGE enum CXLanguageKind { + CXLanguage_Invalid = 0, + CXLanguage_C, + CXLanguage_ObjC, + CXLanguage_CPlusPlus +}; + +/** + * \brief Determine the "language" of the entity referred to by a given cursor. + */ +CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_SOURCE Mapping between cursors and source code + * + * Cursors represent a location within the Abstract Syntax Tree (AST). These + * routines help map between cursors and the physical locations where the + * described entities occur in the source code. The mapping is provided in + * both directions, so one can map from source code to the AST and back. + * + * @{ + */ + +/** + * \brief Map a source location to the cursor that describes the entity at that + * location in the source code. + * + * clang_getCursor() maps an arbitrary source location within a translation + * unit down to the most specific cursor that describes the entity at that + * location. For example, given an expression \c x + y, invoking + * clang_getCursor() with a source location pointing to "x" will return the + * cursor for "x"; similarly for "y". If the cursor points anywhere between + * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor() + * will return a cursor referring to the "+" expression. + * + * \returns a cursor representing the entity at the given source location, or + * a NULL cursor if no such entity can be found. + */ +CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation); + +/** + * \brief Retrieve the physical location of the source constructor referenced + * by the given cursor. + * + * The location of a declaration is typically the location of the name of that + * declaration, where the name of that declaration would occur if it is + * unnamed, or some keyword that introduces that particular declaration. + * The location of a reference is where that reference occurs within the + * source code. + */ +CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor); + +/** + * \brief Retrieve the physical extent of the source construct referenced by + * the given cursor. + * + * The extent of a cursor starts with the file/line/column pointing at the + * first character within the source construct that the cursor refers to and + * ends with the last character withinin that source construct. For a + * declaration, the extent covers the declaration itself. For a reference, + * the extent covers the location of the reference (e.g., where the referenced + * entity was actually used). + */ +CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_TYPES Type information for CXCursors + * + * @{ + */ + +/** + * \brief Describes the kind of type + */ +enum CXTypeKind { + /** + * \brief Reprents an invalid type (e.g., where no type is available). + */ + CXType_Invalid = 0, + + /** + * \brief A type whose specific kind is not exposed via this + * interface. + */ + CXType_Unexposed = 1, + + /* Builtin types */ + CXType_Void = 2, + CXType_Bool = 3, + CXType_Char_U = 4, + CXType_UChar = 5, + CXType_Char16 = 6, + CXType_Char32 = 7, + CXType_UShort = 8, + CXType_UInt = 9, + CXType_ULong = 10, + CXType_ULongLong = 11, + CXType_UInt128 = 12, + CXType_Char_S = 13, + CXType_SChar = 14, + CXType_WChar = 15, + CXType_Short = 16, + CXType_Int = 17, + CXType_Long = 18, + CXType_LongLong = 19, + CXType_Int128 = 20, + CXType_Float = 21, + CXType_Double = 22, + CXType_LongDouble = 23, + CXType_NullPtr = 24, + CXType_Overload = 25, + CXType_Dependent = 26, + CXType_ObjCId = 27, + CXType_ObjCClass = 28, + CXType_ObjCSel = 29, + CXType_FirstBuiltin = CXType_Void, + CXType_LastBuiltin = CXType_ObjCSel, + + CXType_Complex = 100, + CXType_Pointer = 101, + CXType_BlockPointer = 102, + CXType_LValueReference = 103, + CXType_RValueReference = 104, + CXType_Record = 105, + CXType_Enum = 106, + CXType_Typedef = 107, + CXType_ObjCInterface = 108, + CXType_ObjCObjectPointer = 109 +}; + +/** + * \brief The type of an element in the abstract syntax tree. + * + */ +typedef struct { + enum CXTypeKind kind; + void *data[2]; +} CXType; + +/** + * \brief Retrieve the type of a CXCursor (if any). + */ +CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C); + +/** + * \determine Determine whether two CXTypes represent the same type. + * + * \returns non-zero if the CXTypes represent the same type and + zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B); + +/** + * \brief Return the canonical type for a CXType. + * + * Clang's type system explicitly models typedefs and all the ways + * a specific type can be represented. The canonical type is the underlying + * type with all the "sugar" removed. For example, if 'T' is a typedef + * for 'int', the canonical type for 'T' would be 'int'. + */ +CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T); + +/** + * \brief For pointer types, returns the type of the pointee. + * + */ +CINDEX_LINKAGE CXType clang_getPointeeType(CXType T); + +/** + * \brief Return the cursor for the declaration of the given type. + */ +CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T); + + +/** + * \brief Retrieve the spelling of a given CXTypeKind. + */ +CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors + * + * These routines provide the ability to traverse the abstract syntax tree + * using cursors. + * + * @{ + */ + +/** + * \brief Describes how the traversal of the children of a particular + * cursor should proceed after visiting a particular child cursor. + * + * A value of this enumeration type should be returned by each + * \c CXCursorVisitor to indicate how clang_visitChildren() proceed. + */ +enum CXChildVisitResult { + /** + * \brief Terminates the cursor traversal. + */ + CXChildVisit_Break, + /** + * \brief Continues the cursor traversal with the next sibling of + * the cursor just visited, without visiting its children. + */ + CXChildVisit_Continue, + /** + * \brief Recursively traverse the children of this cursor, using + * the same visitor and client data. + */ + CXChildVisit_Recurse +}; + +/** + * \brief Visitor invoked for each cursor found by a traversal. + * + * This visitor function will be invoked for each cursor found by + * clang_visitCursorChildren(). Its first argument is the cursor being + * visited, its second argument is the parent visitor for that cursor, + * and its third argument is the client data provided to + * clang_visitCursorChildren(). + * + * The visitor should return one of the \c CXChildVisitResult values + * to direct clang_visitCursorChildren(). + */ +typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor, + CXCursor parent, + CXClientData client_data); + +/** + * \brief Visit the children of a particular cursor. + * + * This function visits all the direct children of the given cursor, + * invoking the given \p visitor function with the cursors of each + * visited child. The traversal may be recursive, if the visitor returns + * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if + * the visitor returns \c CXChildVisit_Break. + * + * \param parent the cursor whose child may be visited. All kinds of + * cursors can be visited, including invalid cursors (which, by + * definition, have no children). + * + * \param visitor the visitor function that will be invoked for each + * child of \p parent. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the visitor each time it is invoked. + * + * \returns a non-zero value if the traversal was terminated + * prematurely by the visitor returning \c CXChildVisit_Break. + */ +CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, + CXCursorVisitor visitor, + CXClientData client_data); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CURSOR_XREF Cross-referencing in the AST + * + * These routines provide the ability to determine references within and + * across translation units, by providing the names of the entities referenced + * by cursors, follow reference cursors to the declarations they reference, + * and associate declarations with their definitions. + * + * @{ + */ + +/** + * \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced + * by the given cursor. + * + * A Unified Symbol Resolution (USR) is a string that identifies a particular + * entity (function, class, variable, etc.) within a program. USRs can be + * compared across translation units to determine, e.g., when references in + * one translation refer to an entity defined in another translation unit. + */ +CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor); + +/** + * \brief Construct a USR for a specified Objective-C class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name); + +/** + * \brief Construct a USR for a specified Objective-C category. + */ +CINDEX_LINKAGE CXString + clang_constructUSR_ObjCCategory(const char *class_name, + const char *category_name); + +/** + * \brief Construct a USR for a specified Objective-C protocol. + */ +CINDEX_LINKAGE CXString + clang_constructUSR_ObjCProtocol(const char *protocol_name); + + +/** + * \brief Construct a USR for a specified Objective-C instance variable and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name, + CXString classUSR); + +/** + * \brief Construct a USR for a specified Objective-C method and + * the USR for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name, + unsigned isInstanceMethod, + CXString classUSR); + +/** + * \brief Construct a USR for a specified Objective-C property and the USR + * for its containing class. + */ +CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property, + CXString classUSR); + +/** + * \brief Retrieve a name for the entity referenced by this cursor. + */ +CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); + +/** \brief For a cursor that is a reference, retrieve a cursor representing the + * entity that it references. + * + * Reference cursors refer to other entities in the AST. For example, an + * Objective-C superclass reference cursor refers to an Objective-C class. + * This function produces the cursor for the Objective-C class from the + * cursor for the superclass reference. If the input cursor is a declaration or + * definition, it returns that declaration or definition unchanged. + * Otherwise, returns the NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor); + +/** + * \brief For a cursor that is either a reference to or a declaration + * of some entity, retrieve a cursor that describes the definition of + * that entity. + * + * Some entities can be declared multiple times within a translation + * unit, but only one of those declarations can also be a + * definition. For example, given: + * + * \code + * int f(int, int); + * int g(int x, int y) { return f(x, y); } + * int f(int a, int b) { return a + b; } + * int f(int, int); + * \endcode + * + * there are three declarations of the function "f", but only the + * second one is a definition. The clang_getCursorDefinition() + * function will take any cursor pointing to a declaration of "f" + * (the first or fourth lines of the example) or a cursor referenced + * that uses "f" (the call to "f' inside "g") and will return a + * declaration cursor pointing to the definition (the second "f" + * declaration). + * + * If given a cursor for which there is no corresponding definition, + * e.g., because there is no definition of that entity within this + * translation unit, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor); + +/** + * \brief Determine whether the declaration pointed to by this cursor + * is also a definition of that entity. + */ +CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); + +/** + * @} + */ + +/** + * \defgroup CINDEX_CPP C++ AST introspection + * + * The routines in this group provide access information in the ASTs specific + * to C++ language features. + * + * @{ + */ + +/** + * \brief Determine if a C++ member function is declared 'static'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); + +/** + * @} + */ + +/** + * \defgroup CINDEX_LEX Token extraction and manipulation + * + * The routines in this group provide access to the tokens within a + * translation unit, along with a semantic mapping of those tokens to + * their corresponding cursors. + * + * @{ + */ + +/** + * \brief Describes a kind of token. + */ +typedef enum CXTokenKind { + /** + * \brief A token that contains some kind of punctuation. + */ + CXToken_Punctuation, + + /** + * \brief A language keyword. + */ + CXToken_Keyword, + + /** + * \brief An identifier (that is not a keyword). + */ + CXToken_Identifier, + + /** + * \brief A numeric, string, or character literal. + */ + CXToken_Literal, + + /** + * \brief A comment. + */ + CXToken_Comment +} CXTokenKind; + +/** + * \brief Describes a single preprocessing token. + */ +typedef struct { + unsigned int_data[4]; + void *ptr_data; +} CXToken; + +/** + * \brief Determine the kind of the given token. + */ +CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken); + +/** + * \brief Determine the spelling of the given token. + * + * The spelling of a token is the textual representation of that token, e.g., + * the text of an identifier or keyword. + */ +CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken); + +/** + * \brief Retrieve the source location of the given token. + */ +CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit, + CXToken); + +/** + * \brief Retrieve a source range that covers the given token. + */ +CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken); + +/** + * \brief Tokenize the source code described by the given range into raw + * lexical tokens. + * + * \param TU the translation unit whose text is being tokenized. + * + * \param Range the source range in which text should be tokenized. All of the + * tokens produced by tokenization will fall within this source range, + * + * \param Tokens this pointer will be set to point to the array of tokens + * that occur within the given source range. The returned pointer must be + * freed with clang_disposeTokens() before the translation unit is destroyed. + * + * \param NumTokens will be set to the number of tokens in the \c *Tokens + * array. + * + */ +CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, + CXToken **Tokens, unsigned *NumTokens); + +/** + * \brief Annotate the given set of tokens by providing cursors for each token + * that can be mapped to a specific entity within the abstract syntax tree. + * + * This token-annotation routine is equivalent to invoking + * clang_getCursor() for the source locations of each of the + * tokens. The cursors provided are filtered, so that only those + * cursors that have a direct correspondence to the token are + * accepted. For example, given a function call \c f(x), + * clang_getCursor() would provide the following cursors: + * + * * when the cursor is over the 'f', a DeclRefExpr cursor referring to 'f'. + * * when the cursor is over the '(' or the ')', a CallExpr referring to 'f'. + * * when the cursor is over the 'x', a DeclRefExpr cursor referring to 'x'. + * + * Only the first and last of these cursors will occur within the + * annotate, since the tokens "f" and "x' directly refer to a function + * and a variable, respectively, but the parentheses are just a small + * part of the full syntax of the function call expression, which is + * not provided as an annotation. + * + * \param TU the translation unit that owns the given tokens. + * + * \param Tokens the set of tokens to annotate. + * + * \param NumTokens the number of tokens in \p Tokens. + * + * \param Cursors an array of \p NumTokens cursors, whose contents will be + * replaced with the cursors corresponding to each token. + */ +CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU, + CXToken *Tokens, unsigned NumTokens, + CXCursor *Cursors); + +/** + * \brief Free the given set of tokens. + */ +CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU, + CXToken *Tokens, unsigned NumTokens); + +/** + * @} + */ + +/** + * \defgroup CINDEX_DEBUG Debugging facilities + * + * These routines are used for testing and debugging, only, and should not + * be relied upon. + * + * @{ + */ + +/* for debug/testing */ +CINDEX_LINKAGE CXString clang_getCursorKindSpelling(enum CXCursorKind Kind); +CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, + const char **startBuf, + const char **endBuf, + unsigned *startLine, + unsigned *startColumn, + unsigned *endLine, + unsigned *endColumn); +CINDEX_LINKAGE void clang_enableStackTraces(void); +/** + * @} + */ + +/** + * \defgroup CINDEX_CODE_COMPLET Code completion + * + * Code completion involves taking an (incomplete) source file, along with + * knowledge of where the user is actively editing that file, and suggesting + * syntactically- and semantically-valid constructs that the user might want to + * use at that particular point in the source code. These data structures and + * routines provide support for code completion. + * + * @{ + */ + +/** + * \brief A semantic string that describes a code-completion result. + * + * A semantic string that describes the formatting of a code-completion + * result as a single "template" of text that should be inserted into the + * source buffer when a particular code-completion result is selected. + * Each semantic string is made up of some number of "chunks", each of which + * contains some text along with a description of what that text means, e.g., + * the name of the entity being referenced, whether the text chunk is part of + * the template, or whether it is a "placeholder" that the user should replace + * with actual code,of a specific kind. See \c CXCompletionChunkKind for a + * description of the different kinds of chunks. + */ +typedef void *CXCompletionString; + +/** + * \brief A single result of code completion. + */ +typedef struct { + /** + * \brief The kind of entity that this completion refers to. + * + * The cursor kind will be a macro, keyword, or a declaration (one of the + * *Decl cursor kinds), describing the entity that the completion is + * referring to. + * + * \todo In the future, we would like to provide a full cursor, to allow + * the client to extract additional information from declaration. + */ + enum CXCursorKind CursorKind; + + /** + * \brief The code-completion string that describes how to insert this + * code-completion result into the editing buffer. + */ + CXCompletionString CompletionString; +} CXCompletionResult; + +/** + * \brief Describes a single piece of text within a code-completion string. + * + * Each "chunk" within a code-completion string (\c CXCompletionString) is + * either a piece of text with a specific "kind" that describes how that text + * should be interpreted by the client or is another completion string. + */ +enum CXCompletionChunkKind { + /** + * \brief A code-completion string that describes "optional" text that + * could be a part of the template (but is not required). + * + * The Optional chunk is the only kind of chunk that has a code-completion + * string for its representation, which is accessible via + * \c clang_getCompletionChunkCompletionString(). The code-completion string + * describes an additional part of the template that is completely optional. + * For example, optional chunks can be used to describe the placeholders for + * arguments that match up with defaulted function parameters, e.g. given: + * + * \code + * void f(int x, float y = 3.14, double z = 2.71828); + * \endcode + * + * The code-completion string for this function would contain: + * - a TypedText chunk for "f". + * - a LeftParen chunk for "(". + * - a Placeholder chunk for "int x" + * - an Optional chunk containing the remaining defaulted arguments, e.g., + * - a Comma chunk for "," + * - a Placeholder chunk for "float y" + * - an Optional chunk containing the last defaulted argument: + * - a Comma chunk for "," + * - a Placeholder chunk for "double z" + * - a RightParen chunk for ")" + * + * There are many ways to handle Optional chunks. Two simple approaches are: + * - Completely ignore optional chunks, in which case the template for the + * function "f" would only include the first parameter ("int x"). + * - Fully expand all optional chunks, in which case the template for the + * function "f" would have all of the parameters. + */ + CXCompletionChunk_Optional, + /** + * \brief Text that a user would be expected to type to get this + * code-completion result. + * + * There will be exactly one "typed text" chunk in a semantic string, which + * will typically provide the spelling of a keyword or the name of a + * declaration that could be used at the current code point. Clients are + * expected to filter the code-completion results based on the text in this + * chunk. + */ + CXCompletionChunk_TypedText, + /** + * \brief Text that should be inserted as part of a code-completion result. + * + * A "text" chunk represents text that is part of the template to be + * inserted into user code should this particular code-completion result + * be selected. + */ + CXCompletionChunk_Text, + /** + * \brief Placeholder text that should be replaced by the user. + * + * A "placeholder" chunk marks a place where the user should insert text + * into the code-completion template. For example, placeholders might mark + * the function parameters for a function declaration, to indicate that the + * user should provide arguments for each of those parameters. The actual + * text in a placeholder is a suggestion for the text to display before + * the user replaces the placeholder with real code. + */ + CXCompletionChunk_Placeholder, + /** + * \brief Informative text that should be displayed but never inserted as + * part of the template. + * + * An "informative" chunk contains annotations that can be displayed to + * help the user decide whether a particular code-completion result is the + * right option, but which is not part of the actual template to be inserted + * by code completion. + */ + CXCompletionChunk_Informative, + /** + * \brief Text that describes the current parameter when code-completion is + * referring to function call, message send, or template specialization. + * + * A "current parameter" chunk occurs when code-completion is providing + * information about a parameter corresponding to the argument at the + * code-completion point. For example, given a function + * + * \code + * int add(int x, int y); + * \endcode + * + * and the source code \c add(, where the code-completion point is after the + * "(", the code-completion string will contain a "current parameter" chunk + * for "int x", indicating that the current argument will initialize that + * parameter. After typing further, to \c add(17, (where the code-completion + * point is after the ","), the code-completion string will contain a + * "current paremeter" chunk to "int y". + */ + CXCompletionChunk_CurrentParameter, + /** + * \brief A left parenthesis ('('), used to initiate a function call or + * signal the beginning of a function parameter list. + */ + CXCompletionChunk_LeftParen, + /** + * \brief A right parenthesis (')'), used to finish a function call or + * signal the end of a function parameter list. + */ + CXCompletionChunk_RightParen, + /** + * \brief A left bracket ('['). + */ + CXCompletionChunk_LeftBracket, + /** + * \brief A right bracket (']'). + */ + CXCompletionChunk_RightBracket, + /** + * \brief A left brace ('{'). + */ + CXCompletionChunk_LeftBrace, + /** + * \brief A right brace ('}'). + */ + CXCompletionChunk_RightBrace, + /** + * \brief A left angle bracket ('<'). + */ + CXCompletionChunk_LeftAngle, + /** + * \brief A right angle bracket ('>'). + */ + CXCompletionChunk_RightAngle, + /** + * \brief A comma separator (','). + */ + CXCompletionChunk_Comma, + /** + * \brief Text that specifies the result type of a given result. + * + * This special kind of informative chunk is not meant to be inserted into + * the text buffer. Rather, it is meant to illustrate the type that an + * expression using the given completion string would have. + */ + CXCompletionChunk_ResultType, + /** + * \brief A colon (':'). + */ + CXCompletionChunk_Colon, + /** + * \brief A semicolon (';'). + */ + CXCompletionChunk_SemiColon, + /** + * \brief An '=' sign. + */ + CXCompletionChunk_Equal, + /** + * Horizontal space (' '). + */ + CXCompletionChunk_HorizontalSpace, + /** + * Vertical space ('\n'), after which it is generally a good idea to + * perform indentation. + */ + CXCompletionChunk_VerticalSpace +}; + +/** + * \brief Determine the kind of a particular chunk within a completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the kind of the chunk at the index \c chunk_number. + */ +CINDEX_LINKAGE enum CXCompletionChunkKind +clang_getCompletionChunkKind(CXCompletionString completion_string, + unsigned chunk_number); + +/** + * \brief Retrieve the text associated with a particular chunk within a + * completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the text associated with the chunk at index \c chunk_number. + */ +CINDEX_LINKAGE CXString +clang_getCompletionChunkText(CXCompletionString completion_string, + unsigned chunk_number); + +/** + * \brief Retrieve the completion string associated with a particular chunk + * within a completion string. + * + * \param completion_string the completion string to query. + * + * \param chunk_number the 0-based index of the chunk in the completion string. + * + * \returns the completion string associated with the chunk at index + * \c chunk_number, or NULL if that chunk is not represented by a completion + * string. + */ +CINDEX_LINKAGE CXCompletionString +clang_getCompletionChunkCompletionString(CXCompletionString completion_string, + unsigned chunk_number); + +/** + * \brief Retrieve the number of chunks in the given code-completion string. + */ +CINDEX_LINKAGE unsigned +clang_getNumCompletionChunks(CXCompletionString completion_string); + +/** + * \brief Determine the priority of this code completion. + * + * The priority of a code completion indicates how likely it is that this + * particular completion is the completion that the user will select. The + * priority is selected by various internal heuristics. + * + * \param completion_string The completion string to query. + * + * \returns The priority of this completion string. Smaller values indicate + * higher-priority (more likely) completions. + */ +CINDEX_LINKAGE unsigned +clang_getCompletionPriority(CXCompletionString completion_string); + +/** + * \brief Contains the results of code-completion. + * + * This data structure contains the results of code completion, as + * produced by \c clang_codeComplete. Its contents must be freed by + * \c clang_disposeCodeCompleteResults. + */ +typedef struct { + /** + * \brief The code-completion results. + */ + CXCompletionResult *Results; + + /** + * \brief The number of code-completion results stored in the + * \c Results array. + */ + unsigned NumResults; +} CXCodeCompleteResults; + +/** + * \brief Perform code completion at a given location in a source file. + * + * This function performs code completion at a particular file, line, and + * column within source code, providing results that suggest potential + * code snippets based on the context of the completion. The basic model + * for code completion is that Clang will parse a complete source file, + * performing syntax checking up to the location where code-completion has + * been requested. At that point, a special code-completion token is passed + * to the parser, which recognizes this token and determines, based on the + * current location in the C/Objective-C/C++ grammar and the state of + * semantic analysis, what completions to provide. These completions are + * returned via a new \c CXCodeCompleteResults structure. + * + * Code completion itself is meant to be triggered by the client when the + * user types punctuation characters or whitespace, at which point the + * code-completion location will coincide with the cursor. For example, if \c p + * is a pointer, code-completion might be triggered after the "-" and then + * after the ">" in \c p->. When the code-completion location is afer the ">", + * the completion results will provide, e.g., the members of the struct that + * "p" points to. The client is responsible for placing the cursor at the + * beginning of the token currently being typed, then filtering the results + * based on the contents of the token. For example, when code-completing for + * the expression \c p->get, the client should provide the location just after + * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the + * client can filter the results based on the current token text ("get"), only + * showing those results that start with "get". The intent of this interface + * is to separate the relatively high-latency acquisition of code-completion + * results from the filtering of results on a per-character basis, which must + * have a lower latency. + * + * \param CIdx the \c CXIndex instance that will be used to perform code + * completion. + * + * \param source_filename the name of the source file that should be parsed to + * perform code-completion. This source file must be the same as or include the + * filename described by \p complete_filename, or no code-completion results + * will be produced. NOTE: One can also specify NULL for this argument if the + * source file is included in command_line_args. + * + * \param num_command_line_args the number of command-line arguments stored in + * \p command_line_args. + * + * \param command_line_args the command-line arguments to pass to the Clang + * compiler to build the given source file. This should include all of the + * necessary include paths, language-dialect switches, precompiled header + * includes, etc., but should not include any information specific to + * code completion. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for code completion, including the contents of + * those files. The contents and name of these files (as specified by + * CXUnsavedFile) are copied when necessary, so the client only needs to + * guarantee their validity until the call to this function returns. + * + * \param complete_filename the name of the source file where code completion + * should be performed. In many cases, this name will be the same as the + * source filename. However, the completion filename may also be a file + * included by the source file, which is required when producing + * code-completion results for a header. + * + * \param complete_line the line at which code-completion should occur. + * + * \param complete_column the column at which code-completion should occur. + * Note that the column should point just after the syntactic construct that + * initiated code completion, and not in the middle of a lexical token. + * + * \param diag_callback callback function that will receive any diagnostics + * emitted while processing this source file. If NULL, diagnostics will be + * suppressed. + * + * \param diag_client_data client data that will be passed to the diagnostic + * callback function. + * + * \returns if successful, a new CXCodeCompleteResults structure + * containing code-completion results, which should eventually be + * freed with \c clang_disposeCodeCompleteResults(). If code + * completion fails, returns NULL. + */ +CINDEX_LINKAGE +CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, + const char *source_filename, + int num_command_line_args, + const char **command_line_args, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, + const char *complete_filename, + unsigned complete_line, + unsigned complete_column); + +/** + * \brief Free the given set of code-completion results. + */ +CINDEX_LINKAGE +void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); + +/** + * \brief Determine the number of diagnostics produced prior to the + * location where code completion was performed. + */ +CINDEX_LINKAGE +unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results); + +/** + * \brief Retrieve a diagnostic associated with the given code completion. + * + * \param Result the code completion results to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ +CINDEX_LINKAGE +CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, + unsigned Index); + +/** + * @} + */ + + +/** + * \defgroup CINDEX_MISC Miscellaneous utility functions + * + * @{ + */ + +/** + * \brief Return a version string, suitable for showing to a user, but not + * intended to be parsed (the format is not guaranteed to be stable). + */ +CINDEX_LINKAGE CXString clang_getClangVersion(); + +/** + * \brief Return a version string, suitable for showing to a user, but not + * intended to be parsed (the format is not guaranteed to be stable). + */ + + + /** + * \brief Visitor invoked for each file in a translation unit + * (used with clang_getInclusions()). + * + * This visitor function will be invoked by clang_getInclusions() for each + * file included (either at the top-level or by #include directives) within + * a translation unit. The first argument is the file being included, and + * the second and third arguments provide the inclusion stack. The + * array is sorted in order of immediate inclusion. For example, + * the first element refers to the location that included 'included_file'. + */ +typedef void (*CXInclusionVisitor)(CXFile included_file, + CXSourceLocation* inclusion_stack, + unsigned include_len, + CXClientData client_data); + +/** + * \brief Visit the set of preprocessor inclusions in a translation unit. + * The visitor function is called with the provided data for every included + * file. This does not include headers included by the PCH file (unless one + * is inspecting the inclusions in the PCH file itself). + */ +CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu, + CXInclusionVisitor visitor, + CXClientData client_data); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/contrib/llvm/tools/clang/include/clang-c/Makefile b/contrib/llvm/tools/clang/include/clang-c/Makefile new file mode 100644 index 0000000..5e3522f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang-c/Makefile @@ -0,0 +1,31 @@ +LEVEL = ../../../.. +DIRS := + +include $(LEVEL)/Makefile.common + +install-local:: + $(Echo) Installing Clang C API include files + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include/clang-c" ; then \ + cd $(PROJ_SRC_ROOT)/tools/clang/include && \ + for hdr in `find clang-c -type f '!' '(' -name '*~' \ + -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ + -o -name 'Makefile' -o -name '*.td' ')' -print \ + | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ + instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang-c" ; then \ + cd $(PROJ_OBJ_ROOT)/tools/clang/include && \ + for hdr in `find clang-c -type f '!' '(' -name 'Makefile' ')' -print \ + | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h new file mode 100644 index 0000000..5effa90 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h @@ -0,0 +1,243 @@ +//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_APVALUE_H +#define LLVM_CLANG_AST_APVALUE_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" + +namespace clang { + class CharUnits; + class Expr; + +/// APValue - This class implements a discriminated union of [uninitialized] +/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. +class APValue { + typedef llvm::APSInt APSInt; + typedef llvm::APFloat APFloat; +public: + enum ValueKind { + Uninitialized, + Int, + Float, + ComplexInt, + ComplexFloat, + LValue, + Vector + }; +private: + ValueKind Kind; + + struct ComplexAPSInt { + APSInt Real, Imag; + ComplexAPSInt() : Real(1), Imag(1) {} + }; + struct ComplexAPFloat { + APFloat Real, Imag; + ComplexAPFloat() : Real(0.0), Imag(0.0) {} + }; + + struct Vec { + APValue *Elts; + unsigned NumElts; + Vec() : Elts(0), NumElts(0) {} + ~Vec() { delete[] Elts; } + }; + + enum { + MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? + sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) + }; + + union { + void *Aligner; + char Data[MaxSize]; + }; + +public: + APValue() : Kind(Uninitialized) {} + explicit APValue(const APSInt &I) : Kind(Uninitialized) { + MakeInt(); setInt(I); + } + explicit APValue(const APFloat &F) : Kind(Uninitialized) { + MakeFloat(); setFloat(F); + } + explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { + MakeVector(); setVector(E, N); + } + APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { + MakeComplexInt(); setComplexInt(R, I); + } + APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { + MakeComplexFloat(); setComplexFloat(R, I); + } + APValue(const APValue &RHS) : Kind(Uninitialized) { + *this = RHS; + } + APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O); + } + APValue(Expr* B); + + ~APValue() { + MakeUninit(); + } + + ValueKind getKind() const { return Kind; } + bool isUninit() const { return Kind == Uninitialized; } + bool isInt() const { return Kind == Int; } + bool isFloat() const { return Kind == Float; } + bool isComplexInt() const { return Kind == ComplexInt; } + bool isComplexFloat() const { return Kind == ComplexFloat; } + bool isLValue() const { return Kind == LValue; } + bool isVector() const { return Kind == Vector; } + + void print(llvm::raw_ostream &OS) const; + void dump() const; + + APSInt &getInt() { + assert(isInt() && "Invalid accessor"); + return *(APSInt*)(char*)Data; + } + const APSInt &getInt() const { + return const_cast<APValue*>(this)->getInt(); + } + + APFloat &getFloat() { + assert(isFloat() && "Invalid accessor"); + return *(APFloat*)(char*)Data; + } + const APFloat &getFloat() const { + 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; + } + const APSInt &getComplexIntReal() const { + return const_cast<APValue*>(this)->getComplexIntReal(); + } + + APSInt &getComplexIntImag() { + assert(isComplexInt() && "Invalid accessor"); + return ((ComplexAPSInt*)(char*)Data)->Imag; + } + const APSInt &getComplexIntImag() const { + return const_cast<APValue*>(this)->getComplexIntImag(); + } + + APFloat &getComplexFloatReal() { + assert(isComplexFloat() && "Invalid accessor"); + return ((ComplexAPFloat*)(char*)Data)->Real; + } + const APFloat &getComplexFloatReal() const { + return const_cast<APValue*>(this)->getComplexFloatReal(); + } + + APFloat &getComplexFloatImag() { + assert(isComplexFloat() && "Invalid accessor"); + return ((ComplexAPFloat*)(char*)Data)->Imag; + } + const APFloat &getComplexFloatImag() const { + return const_cast<APValue*>(this)->getComplexFloatImag(); + } + + Expr* getLValueBase() const; + CharUnits getLValueOffset() const; + + void setInt(const APSInt &I) { + assert(isInt() && "Invalid accessor"); + *(APSInt*)(char*)Data = I; + } + void setFloat(const APFloat &F) { + assert(isFloat() && "Invalid accessor"); + *(APFloat*)(char*)Data = F; + } + void setVector(const APValue *E, unsigned N) { + assert(isVector() && "Invalid accessor"); + ((Vec*)(char*)Data)->Elts = new APValue[N]; + ((Vec*)(char*)Data)->NumElts = N; + for (unsigned i = 0; i != N; ++i) + ((Vec*)(char*)Data)->Elts[i] = E[i]; + } + void setComplexInt(const APSInt &R, const APSInt &I) { + assert(R.getBitWidth() == I.getBitWidth() && + "Invalid complex int (type mismatch)."); + assert(isComplexInt() && "Invalid accessor"); + ((ComplexAPSInt*)(char*)Data)->Real = R; + ((ComplexAPSInt*)(char*)Data)->Imag = I; + } + void setComplexFloat(const APFloat &R, const APFloat &I) { + assert(&R.getSemantics() == &I.getSemantics() && + "Invalid complex float (type mismatch)."); + assert(isComplexFloat() && "Invalid accessor"); + ((ComplexAPFloat*)(char*)Data)->Real = R; + ((ComplexAPFloat*)(char*)Data)->Imag = I; + } + void setLValue(Expr *B, const CharUnits &O); + + const APValue &operator=(const APValue &RHS); + +private: + void MakeUninit(); + void MakeInt() { + assert(isUninit() && "Bad state change"); + new ((void*)Data) APSInt(1); + Kind = Int; + } + void MakeFloat() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) APFloat(0.0); + Kind = Float; + } + void MakeVector() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) Vec(); + Kind = Vector; + } + void MakeComplexInt() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) ComplexAPSInt(); + Kind = ComplexInt; + } + void MakeComplexFloat() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) ComplexAPFloat(); + Kind = ComplexFloat; + } + void MakeLValue(); +}; + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) { + V.print(OS); + return OS; +} + +} // end namespace clang. + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/AST.h b/contrib/llvm/tools/clang/include/clang/AST/AST.h new file mode 100644 index 0000000..164c5fb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/AST.h @@ -0,0 +1,28 @@ +//===--- AST.h - "Umbrella" header for AST library --------------*- 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 interface to the AST classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_AST_H +#define LLVM_CLANG_AST_AST_H + +// This header exports all AST interfaces. +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/Type.h" +#include "clang/AST/StmtVisitor.h" + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h new file mode 100644 index 0000000..0611395 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h @@ -0,0 +1,92 @@ +//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- 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 ASTConsumer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONSUMER_H +#define LLVM_CLANG_AST_ASTCONSUMER_H + +namespace clang { + class ASTContext; + class CXXRecordDecl; + class DeclGroupRef; + class TagDecl; + class HandleTagDeclDefinition; + class SemaConsumer; // layering violation required for safe SemaConsumer + class VarDecl; + +/// ASTConsumer - This is an abstract interface that should be implemented by +/// clients that read ASTs. This abstraction layer allows the client to be +/// independent of the AST producer (e.g. parser vs AST dump file reader, etc). +class ASTConsumer { + /// \brief Whether this AST consumer also requires information about + /// semantic analysis. + bool SemaConsumer; + + friend class SemaConsumer; + +public: + ASTConsumer() : SemaConsumer(false) { } + + virtual ~ASTConsumer() {} + + /// Initialize - This is called to initialize the consumer, providing the + /// ASTContext. + virtual void Initialize(ASTContext &Context) {} + + /// HandleTopLevelDecl - Handle the specified top-level declaration. This is + /// 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); + + /// HandleTranslationUnit - This method is called when the ASTs for entire + /// translation unit have been parsed. + virtual void HandleTranslationUnit(ASTContext &Ctx) {} + + /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl + /// (e.g. struct, union, enum, class) is completed. This allows the client to + /// hack on the type, which can occur at any point in the file (because these + /// can be defined in declspecs). + virtual void HandleTagDeclDefinition(TagDecl *D) {} + + /// CompleteTentativeDefinition - Callback invoked at the end of a translation + /// unit to notify the consumer that the given tentative definition should be + /// completed. + /// + /// The variable declaration itself will be a tentative + /// definition. If it had an incomplete array type, its type will + /// have already been changed to an array of size 1. However, the + /// declaration remains a tentative definition and has not been + /// modified by the introduction of an implicit zero initializer. + virtual void CompleteTentativeDefinition(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. + /// + /// \param RD The class whose vtable was used. + /// + /// \param DefinitionRequired Whether a definition of this vtable is + /// required in this translation unit; otherwise, it is only needed if + /// it was actually used. + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + + /// PrintStats - If desired, print any statistics. + virtual void PrintStats() {} + + // Support isa/cast/dyn_cast + static bool classof(const ASTConsumer *) { return true; } +}; + +} // end namespace clang. + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h new file mode 100644 index 0000000..87a12cde --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h @@ -0,0 +1,1404 @@ +//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- 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 ASTContext interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONTEXT_H +#define LLVM_CLANG_AST_ASTCONTEXT_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.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/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace llvm { + struct fltSemantics; + class raw_ostream; +} + +namespace clang { + class FileManager; + class ASTRecordLayout; + class BlockExpr; + class CharUnits; + class Diagnostic; + class Expr; + class ExternalASTSource; + class IdentifierTable; + class SelectorTable; + class SourceManager; + class TargetInfo; + // Decls + class DeclContext; + class CXXMethodDecl; + class CXXRecordDecl; + class Decl; + class FieldDecl; + class ObjCIvarDecl; + class ObjCIvarRefExpr; + class ObjCPropertyDecl; + class RecordDecl; + class StoredDeclsMap; + class TagDecl; + class TemplateTypeParmDecl; + class TranslationUnitDecl; + class TypeDecl; + class TypedefDecl; + class UsingDecl; + class UsingShadowDecl; + class UnresolvedSetIterator; + + namespace Builtin { class Context; } + +/// 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 { + std::vector<Type*> Types; + llvm::FoldingSet<ExtQuals> ExtQualNodes; + llvm::FoldingSet<ComplexType> ComplexTypes; + llvm::FoldingSet<PointerType> PointerTypes; + llvm::FoldingSet<BlockPointerType> BlockPointerTypes; + llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; + llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; + llvm::FoldingSet<MemberPointerType> MemberPointerTypes; + llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; + llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; + std::vector<VariableArrayType*> VariableArrayTypes; + llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; + llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes; + llvm::FoldingSet<VectorType> VectorTypes; + llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; + llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; + llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; + llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; + llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; + llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; + llvm::FoldingSet<ElaboratedType> ElaboratedTypes; + llvm::FoldingSet<DependentNameType> DependentNameTypes; + llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; + llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; + + llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; + llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; + + /// \brief The set of nested name specifiers. + /// + /// This set is managed by the NestedNameSpecifier class. + llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; + NestedNameSpecifier *GlobalNestedNameSpecifier; + friend class NestedNameSpecifier; + + /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts. + /// This is lazily created. This is intentionally not serialized. + llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts; + llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; + + /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. + llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions; + + /// \brief Mapping from ObjCContainers to their ObjCImplementations. + llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; + + /// BuiltinVaListType - built-in va list type. + /// This is initially null and set by Sema::LazilyCreateBuiltin when + /// a builtin that takes a valist is encountered. + QualType BuiltinVaListType; + + /// ObjCIdType - a pseudo built-in typedef type (set by Sema). + QualType ObjCIdTypedefType; + + /// ObjCSelType - another pseudo built-in typedef type (set by Sema). + QualType ObjCSelTypedefType; + + /// ObjCProtoType - another pseudo built-in typedef type (set by Sema). + QualType ObjCProtoType; + const RecordType *ProtoStructType; + + /// ObjCClassType - another pseudo built-in typedef type (set by Sema). + QualType ObjCClassTypedefType; + + QualType ObjCConstantStringType; + RecordDecl *CFConstantStringTypeDecl; + + RecordDecl *NSConstantStringTypeDecl; + + RecordDecl *ObjCFastEnumerationStateTypeDecl; + + /// \brief The type for the C FILE type. + TypeDecl *FILEDecl; + + /// \brief The type for the C jmp_buf type. + TypeDecl *jmp_bufDecl; + + /// \brief The type for the C sigjmp_buf type. + TypeDecl *sigjmp_bufDecl; + + /// \brief Type for the Block descriptor for Blocks CodeGen. + RecordDecl *BlockDescriptorType; + + /// \brief Type for the Block descriptor for Blocks CodeGen. + RecordDecl *BlockDescriptorExtendedType; + + /// \brief Keeps track of all declaration attributes. + /// + /// Since so few decls have attrs, we keep them in a hash map instead of + /// wasting space in the Decl class. + llvm::DenseMap<const Decl*, Attr*> DeclAttrs; + + /// \brief Keeps track of the static data member templates from which + /// static data members of class template specializations were instantiated. + /// + /// This data structure stores the mapping from instantiations of static + /// data members to the static data member representations within the + /// class template from which they were instantiated along with the kind + /// of instantiation or specialization (a TemplateSpecializationKind - 1). + /// + /// Given the following example: + /// + /// \code + /// template<typename T> + /// struct X { + /// static T value; + /// }; + /// + /// template<typename T> + /// T X<T>::value = T(17); + /// + /// int *x = &X<int>::value; + /// \endcode + /// + /// This mapping will contain an entry that maps from the VarDecl for + /// X<int>::value to the corresponding VarDecl for X<T>::value (within the + /// class template X) and will be marked TSK_ImplicitInstantiation. + llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *> + InstantiatedFromStaticDataMember; + + /// \brief Keeps track of the declaration from which a UsingDecl was + /// created during instantiation. The source declaration is always + /// a UsingDecl, an UnresolvedUsingValueDecl, or an + /// UnresolvedUsingTypenameDecl. + /// + /// For example: + /// \code + /// template<typename T> + /// struct A { + /// void f(); + /// }; + /// + /// template<typename T> + /// struct B : A<T> { + /// using A<T>::f; + /// }; + /// + /// template struct B<int>; + /// \endcode + /// + /// This mapping will contain an entry that maps from the UsingDecl in + /// B<int> to the UnresolvedUsingDecl in B<T>. + llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl; + + llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*> + InstantiatedFromUsingShadowDecl; + + llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; + + /// \brief Mapping that stores the methods overridden by a given C++ + /// member function. + /// + /// Since most C++ member functions aren't virtual and therefore + /// don't override anything, we store the overridden functions in + /// this map on the side rather than within the CXXMethodDecl structure. + typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector; + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; + + TranslationUnitDecl *TUDecl; + + /// SourceMgr - The associated SourceManager object. + SourceManager &SourceMgr; + + /// LangOpts - The language options used to create the AST associated with + /// this ASTContext object. + LangOptions LangOpts; + + /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. + bool FreeMemory; + llvm::MallocAllocator MallocAlloc; + llvm::BumpPtrAllocator BumpAlloc; + + /// \brief Allocator for partial diagnostics. + PartialDiagnostic::StorageAllocator DiagAllocator; + +public: + const TargetInfo &Target; + IdentifierTable &Idents; + SelectorTable &Selectors; + Builtin::Context &BuiltinInfo; + DeclarationNameTable DeclarationNames; + llvm::OwningPtr<ExternalASTSource> ExternalSource; + clang::PrintingPolicy PrintingPolicy; + + // Typedefs which may be provided defining the structure of Objective-C + // pseudo-builtins + QualType ObjCIdRedefinitionType; + QualType ObjCClassRedefinitionType; + QualType ObjCSelRedefinitionType; + + SourceManager& getSourceManager() { return SourceMgr; } + const SourceManager& getSourceManager() const { return SourceMgr; } + void *Allocate(unsigned Size, unsigned Align = 8) { + return FreeMemory ? MallocAlloc.Allocate(Size, Align) : + BumpAlloc.Allocate(Size, Align); + } + void Deallocate(void *Ptr) { + if (FreeMemory) + MallocAlloc.Deallocate(Ptr); + } + + PartialDiagnostic::StorageAllocator &getDiagAllocator() { + return DiagAllocator; + } + + const LangOptions& getLangOptions() const { return LangOpts; } + + FullSourceLoc getFullLoc(SourceLocation Loc) const { + return FullSourceLoc(Loc,SourceMgr); + } + + /// \brief Retrieve the attributes for the given declaration. + Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } + + /// \brief Erase the attributes corresponding to the given declaration. + void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } + + /// \brief If this variable is an instantiated static data member of a + /// class template specialization, returns the templated static data member + /// from which it was instantiated. + MemberSpecializationInfo *getInstantiatedFromStaticDataMember( + const VarDecl *Var); + + /// \brief Note that the static data member \p Inst is an instantiation of + /// the static data member template \p Tmpl of a class template. + void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, + TemplateSpecializationKind TSK); + + /// \brief If the given using decl is an instantiation of a + /// (possibly unresolved) using decl from a template instantiation, + /// return it. + NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst); + + /// \brief Remember that the using decl \p Inst is an instantiation + /// of the using decl \p Pattern of a class template. + void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern); + + void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, + UsingShadowDecl *Pattern); + UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); + + FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); + + void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + + // Access to the set of methods overridden by the given C++ method. + typedef CXXMethodVector::iterator overridden_cxx_method_iterator; + overridden_cxx_method_iterator + overridden_methods_begin(const CXXMethodDecl *Method) const; + + overridden_cxx_method_iterator + overridden_methods_end(const CXXMethodDecl *Method) const; + + /// \brief Note that the given C++ \p Method overrides the given \p + /// Overridden method. + void addOverriddenMethod(const CXXMethodDecl *Method, + const CXXMethodDecl *Overridden); + + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + + + // Builtin Types. + CanQualType VoidTy; + CanQualType BoolTy; + CanQualType CharTy; + CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. + CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. + CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; + CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; + CanQualType UnsignedLongLongTy, UnsignedInt128Ty; + CanQualType FloatTy, DoubleTy, LongDoubleTy; + CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + CanQualType VoidPtrTy, NullPtrTy; + CanQualType OverloadTy; + CanQualType DependentTy; + CanQualType UndeducedAutoTy; + CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; + + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, + IdentifierTable &idents, SelectorTable &sels, + Builtin::Context &builtins, + bool FreeMemory = true, unsigned size_reserve=0); + + ~ASTContext(); + + /// \brief Attach an external AST source to the AST context. + /// + /// 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); + + /// \brief Retrieve a pointer to the external AST source associated + /// with this AST context, if any. + ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } + + void PrintStats() const; + const std::vector<Type*>& getTypes() const { return Types; } + + //===--------------------------------------------------------------------===// + // Type Constructors + //===--------------------------------------------------------------------===// + +private: + /// getExtQualType - Return a type with extended qualifiers. + QualType getExtQualType(const Type *Base, Qualifiers Quals); + + QualType getTypeDeclTypeSlow(const TypeDecl *Decl); + +public: + /// getAddSpaceQualType - Return the uniqued reference to the type for an + /// address space qualified type with the specified type and address space. + /// The resulting type has a union of the qualifiers from T and the address + /// space. If T already has an address space specifier, it is silently + /// replaced. + QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace); + + /// getObjCGCQualType - Returns the uniqued reference to the type for an + /// objc gc qualified type. The retulting type has a union of the qualifiers + /// from T and the gc attribute. + QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr); + + /// getRestrictType - Returns the uniqued reference to the type for a + /// 'restrict' qualified type. The resulting type has a union of the + /// qualifiers from T and 'restrict'. + QualType getRestrictType(QualType T) { + return T.withFastQualifiers(Qualifiers::Restrict); + } + + /// getVolatileType - Returns the uniqued reference to the type for a + /// 'volatile' qualified type. The resulting type has a union of the + /// qualifiers from T and 'volatile'. + QualType getVolatileType(QualType T); + + /// getConstType - Returns the uniqued reference to the type for a + /// 'const' qualified type. The resulting type has a union of the + /// qualifiers from T and 'const'. + /// + /// It can be reasonably expected that this will always be + /// equivalent to calling T.withConst(). + QualType getConstType(QualType T) { return T.withConst(); } + + /// getNoReturnType - Add or remove the noreturn attribute to the given type + /// which must be a FunctionType or a pointer to an allowable type or a + /// BlockPointer. + QualType getNoReturnType(QualType T, bool AddNoReturn = true); + + /// getCallConvType - Adds the specified calling convention attribute to + /// the given type, which must be a FunctionType or a pointer to an + /// allowable type. + QualType getCallConvType(QualType T, CallingConv CallConv); + + /// getRegParmType - Sets the specified regparm attribute to + /// the given type, which must be a FunctionType or a pointer to an + /// allowable type. + QualType getRegParmType(QualType T, unsigned RegParm); + + /// getComplexType - Return the uniqued reference to the type for a complex + /// number with the specified element type. + QualType getComplexType(QualType T); + CanQualType getComplexType(CanQualType T) { + return CanQualType::CreateUnsafe(getComplexType((QualType) T)); + } + + /// getPointerType - Return the uniqued reference to the type for a pointer to + /// the specified type. + QualType getPointerType(QualType T); + CanQualType getPointerType(CanQualType T) { + return CanQualType::CreateUnsafe(getPointerType((QualType) T)); + } + + /// getBlockPointerType - Return the uniqued reference to the type for a block + /// of the specified type. + QualType getBlockPointerType(QualType T); + + /// This gets the struct used to keep track of the descriptor for pointer to + /// blocks. + QualType getBlockDescriptorType(); + + // Set the type for a Block descriptor type. + void setBlockDescriptorType(QualType T); + /// Get the BlockDescriptorType type, or NULL if it hasn't yet been built. + QualType getRawBlockdescriptorType() { + if (BlockDescriptorType) + return getTagDeclType(BlockDescriptorType); + return QualType(); + } + + /// This gets the struct used to keep track of the extended descriptor for + /// pointer to blocks. + QualType getBlockDescriptorExtendedType(); + + // Set the type for a Block descriptor extended type. + void setBlockDescriptorExtendedType(QualType T); + /// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been + /// built. + QualType getRawBlockdescriptorExtendedType() { + if (BlockDescriptorExtendedType) + return getTagDeclType(BlockDescriptorExtendedType); + return QualType(); + } + + /// This gets the struct used to keep track of pointer to blocks, complete + /// with captured variables. + QualType getBlockParmType(bool BlockHasCopyDispose, + llvm::SmallVectorImpl<const Expr *> &Layout); + + /// This builds the struct used for __block variables. + QualType BuildByRefType(const char *DeclName, QualType Ty); + + /// Returns true iff we need copy/dispose helpers for the given type. + bool BlockRequiresCopying(QualType Ty); + + /// getLValueReferenceType - Return the uniqued reference to the type for an + /// lvalue reference to the specified type. + QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true); + + /// getRValueReferenceType - Return the uniqued reference to the type for an + /// rvalue reference to the specified type. + QualType getRValueReferenceType(QualType T); + + /// getMemberPointerType - Return the uniqued reference to the type for a + /// member pointer to the specified type in the specified class. The class + /// is a Type because it could be a dependent name. + QualType getMemberPointerType(QualType T, const Type *Cls); + + /// getVariableArrayType - Returns a non-unique reference to the type for a + /// variable array of the specified element type. + QualType getVariableArrayType(QualType EltTy, Expr *NumElts, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals, + SourceRange Brackets); + + /// getDependentSizedArrayType - Returns a non-unique reference to + /// the type for a dependently-sized array of the specified element + /// type. FIXME: We will need these to be uniqued, or at least + /// comparable, at some point. + QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals, + SourceRange Brackets); + + /// getIncompleteArrayType - Returns a unique reference to the type for a + /// incomplete array of the specified element type. + QualType getIncompleteArrayType(QualType EltTy, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + + /// getConstantArrayType - Return the unique reference to the type for a + /// constant array of the specified element type. + QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + + /// getVectorType - Return the unique reference to a vector type of + /// the specified element type and size. VectorType must be a built-in type. + QualType getVectorType(QualType VectorType, unsigned NumElts, + bool AltiVec, bool IsPixel); + + /// getExtVectorType - Return the unique reference to an extended vector type + /// of the specified element type and size. VectorType must be a built-in + /// type. + QualType getExtVectorType(QualType VectorType, unsigned NumElts); + + /// getDependentSizedExtVectorType - Returns a non-unique reference to + /// the type for a dependently-sized vector of the specified element + /// type. FIXME: We will need these to be uniqued, or at least + /// comparable, at some point. + QualType getDependentSizedExtVectorType(QualType VectorType, + Expr *SizeExpr, + SourceLocation AttrLoc); + + /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. + /// + QualType getFunctionNoProtoType(QualType ResultTy, + const FunctionType::ExtInfo &Info); + + QualType getFunctionNoProtoType(QualType ResultTy) { + return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); + } + + /// getFunctionType - Return a normal function type with a typed argument + /// list. isVariadic indicates whether the argument list includes '...'. + QualType getFunctionType(QualType ResultTy, const QualType *ArgArray, + unsigned NumArgs, bool isVariadic, + unsigned TypeQuals, bool hasExceptionSpec, + bool hasAnyExceptionSpec, + unsigned NumExs, const QualType *ExArray, + const FunctionType::ExtInfo &Info); + + /// getTypeDeclType - Return the unique reference to the type for + /// the specified type declaration. + QualType getTypeDeclType(const TypeDecl *Decl, + const TypeDecl *PrevDecl = 0) { + assert(Decl && "Passed null for Decl param"); + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (PrevDecl) { + assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + return QualType(PrevDecl->TypeForDecl, 0); + } + + return getTypeDeclTypeSlow(Decl); + } + + /// getTypedefType - Return the unique reference to the type for the + /// specified typename decl. + QualType getTypedefType(const TypedefDecl *Decl); + + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST); + + QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, + QualType Replacement); + + QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, + bool ParameterPack, + IdentifierInfo *Name = 0); + + QualType getTemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs, + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); + + QualType getTemplateSpecializationType(TemplateName T, + const TemplateArgumentListInfo &Args, + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); + + TypeSourceInfo * + getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, + const TemplateArgumentListInfo &Args, + QualType Canon = QualType()); + + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + QualType Canon = QualType()); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const TemplateSpecializationType *TemplateId, + QualType Canon = QualType()); + + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); + + QualType getObjCObjectType(QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols); + + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type + /// for the given ObjCObjectType. + QualType getObjCObjectPointerType(QualType OIT); + + /// getTypeOfType - GCC extension. + QualType getTypeOfExprType(Expr *e); + QualType getTypeOfType(QualType t); + + /// getDecltypeType - C++0x decltype. + QualType getDecltypeType(Expr *e); + + /// getTagDeclType - Return the unique reference to the type for the + /// specified TagDecl (struct/union/class/enum) decl. + QualType getTagDeclType(const TagDecl *Decl); + + /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined + /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4). + CanQualType getSizeType() 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. + QualType getWCharType() const { return WCharTy; } + + /// getSignedWCharType - Return the type of "signed wchar_t". + /// Used when in C++, as a GCC extension. + QualType getSignedWCharType() const; + + /// getUnsignedWCharType - Return the type of "unsigned wchar_t". + /// Used when in C++, as a GCC extension. + QualType getUnsignedWCharType() const; + + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?) + /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). + QualType getPointerDiffType() const; + + // getCFConstantStringType - Return the C structure type used to represent + // constant CFStrings. + QualType getCFConstantStringType(); + + // getNSConstantStringType - Return the C structure type used to represent + // constant NSStrings. + QualType getNSConstantStringType(); + /// Get the structure type used to representation NSStrings, or NULL + /// if it hasn't yet been built. + QualType getRawNSConstantStringType() { + if (NSConstantStringTypeDecl) + return getTagDeclType(NSConstantStringTypeDecl); + return QualType(); + } + void setNSConstantStringType(QualType T); + + + /// Get the structure type used to representation CFStrings, or NULL + /// if it hasn't yet been built. + QualType getRawCFConstantStringType() { + if (CFConstantStringTypeDecl) + return getTagDeclType(CFConstantStringTypeDecl); + return QualType(); + } + void setCFConstantStringType(QualType T); + + // This setter/getter represents the ObjC type for an NSConstantString. + void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); + QualType getObjCConstantStringInterface() const { + return ObjCConstantStringType; + } + + //// This gets the struct used to keep track of fast enumerations. + QualType getObjCFastEnumerationStateType(); + + /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet + /// been built. + QualType getRawObjCFastEnumerationStateType() { + if (ObjCFastEnumerationStateTypeDecl) + return getTagDeclType(ObjCFastEnumerationStateTypeDecl); + return QualType(); + } + + void setObjCFastEnumerationStateType(QualType T); + + /// \brief Set the type for the C FILE type. + void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } + + /// \brief Retrieve the C FILE type. + QualType getFILEType() { + if (FILEDecl) + return getTypeDeclType(FILEDecl); + return QualType(); + } + + /// \brief Set the type for the C jmp_buf type. + void setjmp_bufDecl(TypeDecl *jmp_bufDecl) { + this->jmp_bufDecl = jmp_bufDecl; + } + + /// \brief Retrieve the C jmp_buf type. + QualType getjmp_bufType() { + if (jmp_bufDecl) + return getTypeDeclType(jmp_bufDecl); + return QualType(); + } + + /// \brief Set the type for the C sigjmp_buf type. + void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) { + this->sigjmp_bufDecl = sigjmp_bufDecl; + } + + /// \brief Retrieve the C sigjmp_buf type. + QualType getsigjmp_bufType() { + if (sigjmp_bufDecl) + return getTypeDeclType(sigjmp_bufDecl); + return QualType(); + } + + /// getObjCEncodingForType - Emit the ObjC type encoding for the + /// given type into \arg S. If \arg NameFields is specified then + /// record field names are also encoded. + void getObjCEncodingForType(QualType t, std::string &S, + const FieldDecl *Field=0); + + void getLegacyIntegralTypeEncoding(QualType &t) const; + + // Put the string version of type qualifiers into S. + void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, + std::string &S) const; + + /// getObjCEncodingForMethodDecl - Return the encoded type for this method + /// declaration. + void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); + + /// getObjCEncodingForBlockDecl - Return the encoded type for this block + /// declaration. + void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S); + + /// getObjCEncodingForPropertyDecl - Return the encoded type for + /// this method declaration. If non-NULL, Container must be either + /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should + /// only be NULL when getting encodings for protocol properties. + void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + const Decl *Container, + std::string &S); + + bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, + ObjCProtocolDecl *rProto); + + /// getObjCEncodingTypeSize returns size of type for objective-c encoding + /// purpose in characters. + CharUnits getObjCEncodingTypeSize(QualType t); + + /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by + /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct. + QualType getObjCIdType() const { return ObjCIdTypedefType; } + void setObjCIdType(QualType T); + + void setObjCSelType(QualType T); + QualType getObjCSelType() const { return ObjCSelTypedefType; } + + void setObjCProtoType(QualType QT); + QualType getObjCProtoType() const { return ObjCProtoType; } + + /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by + /// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a + /// struct. + QualType getObjCClassType() const { return ObjCClassTypedefType; } + void setObjCClassType(QualType T); + + void setBuiltinVaListType(QualType T); + QualType getBuiltinVaListType() const { return BuiltinVaListType; } + + /// getCVRQualifiedType - Returns a type with additional const, + /// volatile, or restrict qualifiers. + QualType getCVRQualifiedType(QualType T, unsigned CVR) { + return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); + } + + /// getQualifiedType - Returns a type with additional qualifiers. + QualType getQualifiedType(QualType T, Qualifiers Qs) { + if (!Qs.hasNonFastQualifiers()) + return T.withFastQualifiers(Qs.getFastQualifiers()); + QualifierCollector Qc(Qs); + const Type *Ptr = Qc.strip(T); + return getExtQualType(Ptr, Qc); + } + + /// getQualifiedType - Returns a type with additional qualifiers. + QualType getQualifiedType(const Type *T, Qualifiers Qs) { + if (!Qs.hasNonFastQualifiers()) + return QualType(T, Qs.getFastQualifiers()); + return getExtQualType(T, Qs); + } + + DeclarationName getNameForTemplate(TemplateName Name); + + TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, + UnresolvedSetIterator End); + + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateDecl *Template); + + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + const IdentifierInfo *Name); + TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, + OverloadedOperatorKind Operator); + + enum GetBuiltinTypeError { + GE_None, //< No error + GE_Missing_stdio, //< Missing a type from <stdio.h> + GE_Missing_setjmp //< Missing a type from <setjmp.h> + }; + + /// GetBuiltinType - Return the type for the specified builtin. + QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error); + +private: + CanQualType getFromTargetType(unsigned Type) const; + + //===--------------------------------------------------------------------===// + // Type Predicates. + //===--------------------------------------------------------------------===// + +public: + /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's + /// garbage collection attribute. + /// + Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; + + /// isObjCNSObjectType - Return true if this is an NSObject object with + /// its NSObject attribute set. + bool isObjCNSObjectType(QualType Ty) const; + + //===--------------------------------------------------------------------===// + // Type Sizing and Analysis + //===--------------------------------------------------------------------===// + + /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified + /// scalar floating point type. + const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; + + /// getTypeInfo - Get the size and alignment of the specified complete type in + /// bits. + std::pair<uint64_t, unsigned> getTypeInfo(const Type *T); + std::pair<uint64_t, unsigned> getTypeInfo(QualType T) { + return getTypeInfo(T.getTypePtr()); + } + + /// getTypeSize - Return the size of the specified type, in bits. This method + /// does not work on incomplete types. + uint64_t getTypeSize(QualType T) { + return getTypeInfo(T).first; + } + uint64_t getTypeSize(const Type *T) { + return getTypeInfo(T).first; + } + + /// getCharWidth - Return the size of the character type, in bits + uint64_t getCharWidth() { + return getTypeSize(CharTy); + } + + /// getTypeSizeInChars - Return the size of the specified type, in characters. + /// This method does not work on incomplete types. + CharUnits getTypeSizeInChars(QualType T); + CharUnits getTypeSizeInChars(const Type *T); + + /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. + /// This method does not work on incomplete types. + unsigned getTypeAlign(QualType T) { + return getTypeInfo(T).second; + } + unsigned getTypeAlign(const Type *T) { + return getTypeInfo(T).second; + } + + /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in + /// characters. This method does not work on incomplete types. + CharUnits getTypeAlignInChars(QualType T); + CharUnits getTypeAlignInChars(const Type *T); + + std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T); + + /// getPreferredTypeAlign - Return the "preferred" alignment of the specified + /// type for the current target in bits. This can be different than the ABI + /// alignment in cases where it is beneficial for performance to overalign + /// a data type. + unsigned getPreferredTypeAlign(const Type *T); + + /// getDeclAlign - Return a conservative estimate of the alignment of + /// the specified decl. Note that bitfields do not have a valid alignment, so + /// this method will assert on them. + /// If @p RefAsPointee, references are treated like their underlying type + /// (for alignof), else they're treated like pointers (for CodeGen). + CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false); + + /// getASTRecordLayout - Get or compute information about the layout of the + /// specified record (struct/union/class), which indicates its size and field + /// position information. + const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D); + + /// getASTObjCInterfaceLayout - Get or compute information about the + /// layout of the specified Objective-C interface. + const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D); + + void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS); + + /// getASTObjCImplementationLayout - Get or compute information about + /// the layout of the specified Objective-C implementation. This may + /// differ from the interface if synthesized ivars are present. + const ASTRecordLayout & + getASTObjCImplementationLayout(const ObjCImplementationDecl *D); + + /// getKeyFunction - Get the key function for the given record decl. + /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// + /// ...the first non-pure virtual function that is not inline at the point + /// of class definition. + const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + + void CollectObjCIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<FieldDecl*> &Fields); + + void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + void CollectNonClassIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); + void CollectInheritedProtocols(const Decl *CDecl, + llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); + + //===--------------------------------------------------------------------===// + // Type Operators + //===--------------------------------------------------------------------===// + + /// getCanonicalType - Return the canonical (structural) type corresponding to + /// the specified potentially non-canonical type. The non-canonical version + /// of a type may have many "decorated" versions of types. Decorators can + /// include typedefs, 'typeof' operators, etc. The returned type is guaranteed + /// to be free of any of these, allowing two canonical types to be compared + /// for exact equality with a simple pointer comparison. + CanQualType getCanonicalType(QualType T); + const Type *getCanonicalType(const Type *T) { + return T->getCanonicalTypeInternal().getTypePtr(); + } + + /// getCanonicalParamType - Return the canonical parameter type + /// corresponding to the specific potentially non-canonical one. + /// Qualifiers are stripped off, functions are turned into function + /// pointers, and arrays decay one level into pointers. + CanQualType getCanonicalParamType(QualType T); + + /// \brief Determine whether the given types are equivalent. + bool hasSameType(QualType T1, QualType T2) { + return getCanonicalType(T1) == getCanonicalType(T2); + } + + /// \brief Returns this type as a completely-unqualified array type, + /// capturing the qualifiers in Quals. This will remove the minimal amount of + /// sugaring from the types, similar to the behavior of + /// QualType::getUnqualifiedType(). + /// + /// \param T is the qualified type, which may be an ArrayType + /// + /// \param Quals will receive the full set of qualifiers that were + /// applied to the array. + /// + /// \returns if this is an array type, the completely unqualified array type + /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). + QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals); + + /// \brief Determine whether the given types are equivalent after + /// cvr-qualifiers have been removed. + bool hasSameUnqualifiedType(QualType T1, QualType T2) { + CanQualType CT1 = getCanonicalType(T1); + CanQualType CT2 = getCanonicalType(T2); + + Qualifiers Quals; + QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals); + QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals); + return UnqualT1 == UnqualT2; + } + + /// \brief Retrieves the "canonical" declaration of + + /// \brief Retrieves the "canonical" nested name specifier for a + /// given nested name specifier. + /// + /// The canonical nested name specifier is a nested name specifier + /// that uniquely identifies a type or namespace within the type + /// system. For example, given: + /// + /// \code + /// namespace N { + /// struct S { + /// template<typename T> struct X { typename T* type; }; + /// }; + /// } + /// + /// template<typename T> struct Y { + /// typename N::S::X<T>::type member; + /// }; + /// \endcode + /// + /// Here, the nested-name-specifier for N::S::X<T>:: will be + /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined + /// by declarations in the type system and the canonical type for + /// the template type parameter 'T' is template-param-0-0. + NestedNameSpecifier * + getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Retrieves the canonical representation of the given + /// calling convention. + CallingConv getCanonicalCallConv(CallingConv CC) { + if (CC == CC_C) + return CC_Default; + return CC; + } + + /// \brief Determines whether two calling conventions name the same + /// calling convention. + bool isSameCallConv(CallingConv lcc, CallingConv rcc) { + return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc)); + } + + /// \brief Retrieves the "canonical" template name that refers to a + /// given template. + /// + /// The canonical template name is the simplest expression that can + /// be used to refer to a given template. For most templates, this + /// expression is just the template declaration itself. For example, + /// the template std::vector can be referred to via a variety of + /// names---std::vector, ::std::vector, vector (if vector is in + /// scope), etc.---but all of these names map down to the same + /// TemplateDecl, which is used to form the canonical template name. + /// + /// Dependent template names are more interesting. Here, the + /// template name could be something like T::template apply or + /// std::allocator<T>::template rebind, where the nested name + /// specifier itself is dependent. In this case, the canonical + /// template name uses the shortest form of the dependent + /// nested-name-specifier, which itself contains all canonical + /// types, values, and templates. + TemplateName getCanonicalTemplateName(TemplateName Name); + + /// \brief Determine whether the given template names refer to the same + /// template. + bool hasSameTemplateName(TemplateName X, TemplateName Y); + + /// \brief Retrieve the "canonical" template argument. + /// + /// The canonical template argument is the simplest template argument + /// (which may be a type, value, expression, or declaration) that + /// expresses the value of the argument. + TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg); + + /// Type Query functions. If the type is an instance of the specified class, + /// return the Type pointer for the underlying maximally pretty type. This + /// is a member of ASTContext because this may need to do some amount of + /// canonicalization, e.g. to move type qualifiers into the element type. + const ArrayType *getAsArrayType(QualType T); + const ConstantArrayType *getAsConstantArrayType(QualType T) { + return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T)); + } + const VariableArrayType *getAsVariableArrayType(QualType T) { + return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T)); + } + const IncompleteArrayType *getAsIncompleteArrayType(QualType T) { + return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T)); + } + const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) { + return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T)); + } + + /// getBaseElementType - Returns the innermost element type of an array type. + /// For example, will return "int" for int[m][n] + QualType getBaseElementType(const ArrayType *VAT); + + /// getBaseElementType - Returns the innermost element type of a type + /// (which needn't actually be an array type). + QualType getBaseElementType(QualType QT); + + /// getConstantArrayElementCount - Returns number of constant array elements. + uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; + + /// getArrayDecayedType - Return the properly qualified result of decaying the + /// specified array type to a pointer. This operation is non-trivial when + /// handling typedefs etc. The canonical type of "T" must be an array type, + /// this returns a pointer to a properly qualified element of the array. + /// + /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. + QualType getArrayDecayedType(QualType T); + + /// getPromotedIntegerType - Returns the type that Promotable will + /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable + /// integer type. + QualType getPromotedIntegerType(QualType PromotableType); + + /// \brief Whether this is a promotable bitfield reference according + /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). + /// + /// \returns the type this bit-field will promote to, or NULL if no + /// promotion occurs. + QualType isPromotableBitField(Expr *E); + + /// getIntegerTypeOrder - Returns the highest ranked integer type: + /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If + /// LHS < RHS, return -1. + int getIntegerTypeOrder(QualType LHS, QualType RHS); + + /// getFloatingTypeOrder - Compare the rank of the two specified floating + /// point types, ignoring the domain of the type (i.e. 'double' == + /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If + /// LHS < RHS, return -1. + int getFloatingTypeOrder(QualType LHS, QualType RHS); + + /// getFloatingTypeOfSizeWithinDomain - Returns a real floating + /// point or a complex type (based on typeDomain/typeSize). + /// 'typeDomain' is a real floating point or complex type. + /// 'typeSize' is a real floating point or complex type. + QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, + QualType typeDomain) const; + +private: + // Helper for integer ordering + unsigned getIntegerRank(Type* T); + +public: + + //===--------------------------------------------------------------------===// + // Type Compatibility Predicates + //===--------------------------------------------------------------------===// + + /// Compatibility predicates used to check assignment expressions. + bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 + + bool typesAreBlockPointerCompatible(QualType, QualType); + + bool isObjCIdType(QualType T) const { + return T == ObjCIdTypedefType; + } + bool isObjCClassType(QualType T) const { + return T == ObjCClassTypedefType; + } + bool isObjCSelType(QualType T) const { + return T == ObjCSelTypedefType; + } + bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); + bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, + bool ForCompare); + + // Check the safety of assignment from LHS to RHS + bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + bool canAssignObjCInterfaces(const ObjCObjectType *LHS, + const ObjCObjectType *RHS); + bool canAssignObjCInterfacesInBlockPointer( + const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); + QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + + // Functions for calculating composite types + QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); + QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); + + QualType mergeObjCGCQualifiers(QualType, QualType); + + /// UsualArithmeticConversionsType - handles the various conversions + /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) + /// and returns the result type of that conversion. + QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); + + //===--------------------------------------------------------------------===// + // Integer Predicates + //===--------------------------------------------------------------------===// + + // The width of an integer, as defined in C99 6.2.6.2. This is the number + // of bits in an integer type excluding any padding bits. + unsigned getIntWidth(QualType T); + + // Per C99 6.2.5p6, for every signed integer type, there is a corresponding + // unsigned integer type. This method takes a signed type, and returns the + // corresponding unsigned integer type. + QualType getCorrespondingUnsignedType(QualType T); + + //===--------------------------------------------------------------------===// + // Type Iterators. + //===--------------------------------------------------------------------===// + + typedef std::vector<Type*>::iterator type_iterator; + typedef std::vector<Type*>::const_iterator const_type_iterator; + + type_iterator types_begin() { return Types.begin(); } + type_iterator types_end() { return Types.end(); } + const_type_iterator types_begin() const { return Types.begin(); } + const_type_iterator types_end() const { return Types.end(); } + + //===--------------------------------------------------------------------===// + // Integer Values + //===--------------------------------------------------------------------===// + + /// MakeIntValue - Make an APSInt of the appropriate width and + /// signedness for the given \arg Value and integer \arg Type. + llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) { + llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType()); + Res = Value; + return Res; + } + + /// \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. + ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); + + /// \brief Set the implementation of ObjCInterfaceDecl. + void setObjCImplementation(ObjCInterfaceDecl *IFaceD, + ObjCImplementationDecl *ImplD); + /// \brief Set the implementation of ObjCCategoryDecl. + void setObjCImplementation(ObjCCategoryDecl *CatD, + ObjCCategoryImplDecl *ImplD); + + /// \brief Allocate an uninitialized TypeSourceInfo. + /// + /// The caller should initialize the memory held by TypeSourceInfo using + /// the TypeLoc wrappers. + /// + /// \param T the type that will be the basis for type source info. This type + /// should refer to how the declarator was written in source code, not to + /// what type semantic analysis resolved the declarator to. + /// + /// \param Size the size of the type info to create, or 0 if the size + /// should be calculated based on the type. + TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0); + + /// \brief Allocate a TypeSourceInfo where all locations have been + /// initialized to a given location, which defaults to the empty + /// location. + TypeSourceInfo * + getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); + + /// \brief Add a deallocation callback that will be invoked when the + /// ASTContext is destroyed. + /// + /// \brief Callback A callback function that will be invoked on destruction. + /// + /// \brief Data Pointer data that will be provided to the callback function + /// when it is called. + void AddDeallocation(void (*Callback)(void*), void *Data); + +private: + ASTContext(const ASTContext&); // DO NOT IMPLEMENT + void operator=(const ASTContext&); // DO NOT IMPLEMENT + + void InitBuiltinTypes(); + void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); + + // Return the ObjC type encoding for a given type. + void getObjCEncodingForTypeImpl(QualType t, std::string &S, + bool ExpandPointedToStructures, + bool ExpandStructures, + const FieldDecl *Field, + bool OutermostType = false, + bool EncodingProperty = false); + + const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, + const ObjCImplementationDecl *Impl); + +private: + /// \brief A set of deallocations that should be performed when the + /// ASTContext is destroyed. + llvm::SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations; + + // FIXME: This currently contains the set of StoredDeclMaps used + // by DeclContext objects. This probably should not be in ASTContext, + // but we include it here so that ASTContext can quickly deallocate them. + llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; + friend class DeclContext; + friend class DeclarationNameTable; + void ReleaseDeclContextMaps(); +}; + +/// @brief Utility function for constructing a nullary selector. +static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(0, &II); +} + +/// @brief Utility function for constructing an unary selector. +static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(1, &II); +} + +} // end namespace clang + +// 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.) +/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): +/// @code +/// // Default alignment (8) +/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); +/// // Specific alignment +/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The ASTContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new(size_t Bytes, clang::ASTContext &C, + size_t Alignment) throw () { + return C.Allocate(Bytes, Alignment); +} +/// @brief Placement delete companion to the new above. +/// +/// This operator is just a companion to the new above. There is no way of +/// 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, clang::ASTContext &C, size_t) + throw () { + 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. +/// Usage looks like this (assuming there's an ASTContext 'Context' in scope): +/// @code +/// // Default alignment (8) +/// char *data = new (Context) char[10]; +/// // Specific alignment +/// char *data = new (Context, 4) char[10]; +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The ASTContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new[](size_t Bytes, clang::ASTContext& C, + size_t Alignment = 8) throw () { + return C.Allocate(Bytes, Alignment); +} + +/// @brief Placement delete[] companion to the new[] above. +/// +/// This operator is just a companion to the new[] above. There is no way of +/// 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, clang::ASTContext &C, size_t) + throw () { + C.Deallocate(Ptr); +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h new file mode 100644 index 0000000..7cbf3a5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h @@ -0,0 +1,47 @@ +//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- 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_DIAGNOSTICAST_H +#define LLVM_CLANG_DIAGNOSTICAST_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define ASTSTART +#include "clang/Basic/DiagnosticASTKinds.inc" +#undef DIAG + NUM_BUILTIN_AST_DIAGNOSTICS + }; + } // end namespace diag + + /// \brief Diagnostic argument formatting function for diagnostics that + /// involve AST nodes. + /// + /// This function formats diagnostic arguments for various AST nodes, + /// including types, declaration names, nested name specifiers, and + /// declaration contexts, into strings that can be printed as part of + /// diagnostics. It is meant to be used as the argument to + /// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext + /// pointer. + void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind, + intptr_t Val, + const char *Modifier, + unsigned ModLen, + const char *Argument, + unsigned ArgLen, + const Diagnostic::ArgumentValue *PrevArgs, + unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output, + void *Cookie); +} // 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 new file mode 100644 index 0000000..7975c43 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h @@ -0,0 +1,240 @@ +//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- 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 ASTImporter class which imports AST nodes from one +// context into another context. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_ASTIMPORTER_H +#define LLVM_CLANG_AST_ASTIMPORTER_H + +#include "clang/AST/Type.h" +#include "clang/AST/DeclarationName.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class ASTContext; + class Decl; + class DeclContext; + class Diagnostic; + class Expr; + class FileManager; + class IdentifierInfo; + class NestedNameSpecifier; + class Stmt; + class TypeSourceInfo; + + /// \brief Imports selected nodes from one AST context into another context, + /// merging AST nodes where appropriate. + class ASTImporter { + public: + typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet; + + private: + /// \brief The contexts we're importing to and from. + ASTContext &ToContext, &FromContext; + + /// \brief The file managers we're importing to and from. + FileManager &ToFileManager, &FromFileManager; + + /// \brief The diagnostics object that we should use to emit diagnostics. + Diagnostic &Diags; + + /// \brief Mapping from the already-imported types in the "from" context + /// to the corresponding types in the "to" context. + llvm::DenseMap<Type *, Type *> ImportedTypes; + + /// \brief Mapping from the already-imported declarations in the "from" + /// context to the corresponding declarations in the "to" context. + llvm::DenseMap<Decl *, Decl *> ImportedDecls; + + /// \brief Mapping from the already-imported statements in the "from" + /// context to the corresponding statements in the "to" context. + llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; + + /// \brief Mapping from the already-imported FileIDs in the "from" source + /// manager to the corresponding FileIDs in the "to" source manager. + llvm::DenseMap<unsigned, FileID> ImportedFileIDs; + + /// \brief Imported, anonymous tag declarations that are missing their + /// corresponding typedefs. + llvm::SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs; + + /// \brief Declaration (from, to) pairs that are known not to be equivalent + /// (which we have already complained about). + NonEquivalentDeclSet NonEquivalentDecls; + + public: + ASTImporter(Diagnostic &Diags, + ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager); + + virtual ~ASTImporter(); + + /// \brief Import the given type from the "from" context into the "to" + /// context. + /// + /// \returns the equivalent type in the "to" context, or a NULL type if + /// an error occurred. + QualType Import(QualType FromT); + + /// \brief Import the given type source information from the + /// "from" context into the "to" context. + /// + /// \returns the equivalent type source information in the "to" + /// context, or NULL if an error occurred. + TypeSourceInfo *Import(TypeSourceInfo *FromTSI); + + /// \brief Import the given declaration from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent declaration in the "to" context, or a NULL type + /// if an error occurred. + Decl *Import(Decl *FromD); + + /// \brief Import the given declaration context from the "from" + /// AST context into the "to" AST context. + /// + /// \returns the equivalent declaration context in the "to" + /// context, or a NULL type if an error occurred. + DeclContext *ImportContext(DeclContext *FromDC); + + /// \brief Import the given expression from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent expression in the "to" context, or NULL if + /// an error occurred. + Expr *Import(Expr *FromE); + + /// \brief Import the given statement from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent statement in the "to" context, or NULL if + /// an error occurred. + Stmt *Import(Stmt *FromS); + + /// \brief Import the given nested-name-specifier from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent nested-name-specifier in the "to" + /// context, or NULL if an error occurred. + NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); + + /// \brief Import the given source location from the "from" context into + /// the "to" context. + /// + /// \returns the equivalent source location in the "to" context, or an + /// invalid source location if an error occurred. + SourceLocation Import(SourceLocation FromLoc); + + /// \brief Import the given source range from the "from" context into + /// the "to" context. + /// + /// \returns the equivalent source range in the "to" context, or an + /// invalid source location if an error occurred. + SourceRange Import(SourceRange FromRange); + + /// \brief Import the given declaration name from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent declaration name in the "to" context, + /// or an empty declaration name if an error occurred. + DeclarationName Import(DeclarationName FromName); + + /// \brief Import the given identifier from the "from" context + /// into the "to" context. + /// + /// \returns the equivalent identifier in the "to" context. + IdentifierInfo *Import(IdentifierInfo *FromId); + + /// \brief Import the given Objective-C selector from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent selector in the "to" context. + Selector Import(Selector FromSel); + + /// \brief Import the given file ID from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent file ID in the source manager of the "to" + /// context. + FileID Import(FileID); + + /// \brief Cope with a name conflict when importing a declaration into the + /// given context. + /// + /// This routine is invoked whenever there is a name conflict while + /// importing a declaration. The returned name will become the name of the + /// imported declaration. By default, the returned name is the same as the + /// original name, leaving the conflict unresolve such that name lookup + /// for this name is likely to find an ambiguity later. + /// + /// Subclasses may override this routine to resolve the conflict, e.g., by + /// renaming the declaration being imported. + /// + /// \param Name the name of the declaration being imported, which conflicts + /// with other declarations. + /// + /// \param DC the declaration context (in the "to" AST context) in which + /// the name is being imported. + /// + /// \param IDNS the identifier namespace in which the name will be found. + /// + /// \param Decls the set of declarations with the same name as the + /// declaration being imported. + /// + /// \param NumDecls the number of conflicting declarations in \p Decls. + /// + /// \returns the name that the newly-imported declaration should have. + virtual DeclarationName HandleNameConflict(DeclarationName Name, + DeclContext *DC, + unsigned IDNS, + NamedDecl **Decls, + unsigned NumDecls); + + /// \brief Retrieve the context that AST nodes are being imported into. + ASTContext &getToContext() const { return ToContext; } + + /// \brief Retrieve the context that AST nodes are being imported from. + ASTContext &getFromContext() const { return FromContext; } + + /// \brief Retrieve the file manager that AST nodes are being imported into. + FileManager &getToFileManager() const { return ToFileManager; } + + /// \brief Retrieve the file manager that AST nodes are being imported from. + FileManager &getFromFileManager() const { return FromFileManager; } + + /// \brief Retrieve the diagnostic formatter. + Diagnostic &getDiags() const { return Diags; } + + /// \brief Report a diagnostic in the "to" context. + DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); + + /// \brief Report a diagnostic in the "from" context. + DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); + + /// \brief Return the set of declarations that we know are not equivalent. + NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } + + /// \brief Note that we have imported the "from" declaration by mapping it + /// to the (potentially-newly-created) "to" declaration. + /// + /// \returns \p To + Decl *Imported(Decl *From, Decl *To); + + /// \brief Determine whether the given types are structurally + /// equivalent. + bool IsStructurallyEquivalent(QualType From, QualType To); + }; +} + +#endif // LLVM_CLANG_AST_ASTIMPORTER_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h new file mode 100644 index 0000000..217dfad --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h @@ -0,0 +1,397 @@ +//===- ASTVector.h - Vector that uses ASTContext for allocation --*- 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 ASTVector, a vector ADT whose contents are +// allocated using the allocator associated with an ASTContext.. +// +//===----------------------------------------------------------------------===// + +// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. +// We can refactor this core logic into something common. + +#ifndef LLVM_CLANG_AST_VECTOR +#define LLVM_CLANG_AST_VECTOR + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/PointerIntPair.h" +#include <algorithm> +#include <memory> +#include <cstring> + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else + // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear + // is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace clang { + +template<typename T> +class ASTVector { + T *Begin, *End, *Capacity; + + void setEnd(T *P) { this->End = P; } + +public: + // Default ctor - Initialize to empty. + explicit ASTVector(ASTContext &C, unsigned N = 0) + : Begin(NULL), End(NULL), Capacity(NULL) { + reserve(C, N); + } + + ~ASTVector() { + if (llvm::is_class<T>::value) { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + } + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return 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());} + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + + reference operator[](unsigned idx) { + assert(Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert(Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + if (llvm::is_class<T>::value) { + destroy_range(Begin, End); + } + End = Begin; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + void push_back(const_reference Elt, ASTContext &C) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(C); + goto Retry; + } + + void reserve(ASTContext &C, unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(C, N); + } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return Capacity - Begin; } + + /// append - Add the specified range to the end of the SmallVector. + /// + template<typename in_iter> + void append(ASTContext &C, in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + + if (NumInputs == 0) + return; + + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + // TODO: NEED To compile time dispatch on whether in_iter is a random access + // iterator to use the fast uninitialized_copy. + std::uninitialized_copy(in_start, in_end, this->end()); + this->setEnd(this->end() + NumInputs); + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(ASTContext &C, size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->setEnd(this->end() + NumInputs); + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + iterator insert(ASTContext &C, iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + push_back(Elt); + return this->end()-1; + } + + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(this->back()); + this->setEnd(this->end()+1); + // Push everything else over. + std::copy_backward(I, this->end()-1, this->end()); + *I = Elt; + return I; + } + size_t EltNo = I-this->begin(); + this->grow(C); + I = this->begin()+EltNo; + goto Retry; + } + + iterator insert(ASTContext &C, iterator I, size_type NumToInsert, + const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + append(C, NumToInsert, Elt); + return this->end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template<typename ItTy> + iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) { + if (I == this->end()) { // Important special case for empty vector. + append(C, From, To); + return this->end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (; NumOverwritten > 0; --NumOverwritten) { + *I = *From; + ++I; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + void resize(ASTContext &C, unsigned N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(C, N); + construct_range(this->end(), this->begin()+N, NV); + this->setEnd(this->begin()+N); + } + } + +private: + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(ASTContext &C, size_type MinSize = 1); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + +protected: + iterator capacity_ptr() { return (iterator)this->Capacity; } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void ASTVector<T>::grow(ASTContext &C, size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + + // Allocate the memory from the ASTContext. + T *NewElts = new (C) T[NewCapacity]; + + // Copy the elements over. + if (llvm::is_class<T>::value) { + std::uninitialized_copy(Begin, End, NewElts); + // Destroy the original elements. + destroy_range(Begin, End); + } + else { + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + } + + C.Deallocate(Begin); + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +} // end: clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h new file mode 100644 index 0000000..3240e50 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h @@ -0,0 +1,614 @@ +//===--- Attr.h - Classes for representing expressions ----------*- 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 Attr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTR_H +#define LLVM_CLANG_AST_ATTR_H + +#include "llvm/Support/Casting.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <cstring> +#include <algorithm> +using llvm::dyn_cast; + +namespace clang { + class ASTContext; + class IdentifierInfo; + class ObjCInterfaceDecl; +} + +// Defined in ASTContext.h +void *operator new(size_t Bytes, clang::ASTContext &C, + size_t Alignment = 16) throw (); + +// 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, clang::ASTContext &C, size_t) + throw (); + +namespace clang { + +/// Attr - This represents one attribute. +class Attr { +public: + enum Kind { + Alias, + Aligned, + AlignMac68k, + AlwaysInline, + AnalyzerNoReturn, // Clang-specific. + Annotate, + AsmLabel, // Represent GCC asm label extension. + BaseCheck, + Blocks, + CDecl, + Cleanup, + Const, + Constructor, + Deprecated, + Destructor, + FastCall, + Final, + Format, + FormatArg, + GNUInline, + Hiding, + IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. + IBOutletCollectionKind, // Clang-specific. + IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. + Malloc, + MaxFieldAlignment, + NoDebug, + NoInline, + NonNull, + NoReturn, + NoThrow, + ObjCException, + ObjCNSObject, + Override, + CFReturnsRetained, // Clang/Checker-specific. + CFReturnsNotRetained, // Clang/Checker-specific. + NSReturnsRetained, // Clang/Checker-specific. + NSReturnsNotRetained, // Clang/Checker-specific. + Overloadable, // Clang-specific + Packed, + Pure, + Regparm, + ReqdWorkGroupSize, // OpenCL-specific + Section, + Sentinel, + StdCall, + ThisCall, + TransparentUnion, + Unavailable, + Unused, + Used, + Visibility, + WarnUnusedResult, + Weak, + WeakImport, + WeakRef, + + FIRST_TARGET_ATTRIBUTE, + DLLExport, + DLLImport, + MSP430Interrupt, + X86ForceAlignArgPointer + }; + +private: + Attr *Next; + Kind AttrKind; + bool Inherited : 1; + +protected: + void* operator new(size_t bytes) throw() { + assert(0 && "Attrs cannot be allocated with regular 'new'."); + return 0; + } + void operator delete(void* data) throw() { + assert(0 && "Attrs cannot be released with regular 'delete'."); + } + +protected: + Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} + virtual ~Attr() { + assert(Next == 0 && "Destroy didn't work"); + } +public: + virtual void Destroy(ASTContext &C); + + /// \brief Whether this attribute should be merged to new + /// declarations. + virtual bool isMerged() const { return true; } + + Kind getKind() const { return AttrKind; } + + Attr *getNext() { return Next; } + const Attr *getNext() const { return Next; } + void setNext(Attr *next) { Next = next; } + + template<typename T> const T *getNext() const { + for (const Attr *attr = getNext(); attr; attr = attr->getNext()) + if (const T *V = dyn_cast<T>(attr)) + return V; + return 0; + } + + bool isInherited() const { return Inherited; } + void setInherited(bool value) { Inherited = value; } + + void addAttr(Attr *attr) { + assert((attr != 0) && "addAttr(): attr is null"); + + // FIXME: This doesn't preserve the order in any way. + attr->Next = Next; + Next = attr; + } + + // Clone this attribute. + virtual Attr* clone(ASTContext &C) const = 0; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *) { return true; } +}; + +class AttrWithString : public Attr { +private: + const char *Str; + unsigned StrLen; +protected: + AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s); + llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); } + void ReplaceString(ASTContext &C, llvm::StringRef newS); +public: + virtual void Destroy(ASTContext &C); +}; + +#define DEF_SIMPLE_ATTR(ATTR) \ +class ATTR##Attr : public Attr { \ +public: \ + ATTR##Attr() : Attr(ATTR) {} \ + virtual Attr *clone(ASTContext &C) const; \ + static bool classof(const Attr *A) { return A->getKind() == ATTR; } \ + static bool classof(const ATTR##Attr *A) { return true; } \ +} + +DEF_SIMPLE_ATTR(Packed); + +/// \brief Attribute for specifying a maximum field alignment; this is only +/// valid on record decls. +class MaxFieldAlignmentAttr : public Attr { + unsigned Alignment; + +public: + MaxFieldAlignmentAttr(unsigned alignment) + : Attr(MaxFieldAlignment), Alignment(alignment) {} + + /// getAlignment - The specified alignment in bits. + unsigned getAlignment() const { return Alignment; } + + virtual Attr* clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == MaxFieldAlignment; + } + static bool classof(const MaxFieldAlignmentAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(AlignMac68k); + +class AlignedAttr : public Attr { + unsigned Alignment; +public: + AlignedAttr(unsigned alignment) + : Attr(Aligned), Alignment(alignment) {} + + /// getAlignment - The specified alignment in bits. + unsigned getAlignment() const { return Alignment; } + + /// getMaxAlignment - Get the maximum alignment of attributes on this list. + unsigned getMaxAlignment() const { + const AlignedAttr *Next = getNext<AlignedAttr>(); + if (Next) + return std::max(Next->getMaxAlignment(), Alignment); + else + return Alignment; + } + + virtual Attr* clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == Aligned; + } + static bool classof(const AlignedAttr *A) { return true; } +}; + +class AnnotateAttr : public AttrWithString { +public: + AnnotateAttr(ASTContext &C, llvm::StringRef ann) + : AttrWithString(Annotate, C, ann) {} + + llvm::StringRef getAnnotation() const { return getString(); } + + virtual Attr* clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == Annotate; + } + static bool classof(const AnnotateAttr *A) { return true; } +}; + +class AsmLabelAttr : public AttrWithString { +public: + AsmLabelAttr(ASTContext &C, llvm::StringRef L) + : AttrWithString(AsmLabel, C, L) {} + + llvm::StringRef getLabel() const { return getString(); } + + virtual Attr* clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == AsmLabel; + } + static bool classof(const AsmLabelAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(AlwaysInline); + +class AliasAttr : public AttrWithString { +public: + AliasAttr(ASTContext &C, llvm::StringRef aliasee) + : AttrWithString(Alias, C, aliasee) {} + + llvm::StringRef getAliasee() const { return getString(); } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Alias; } + static bool classof(const AliasAttr *A) { return true; } +}; + +class ConstructorAttr : public Attr { + int priority; +public: + ConstructorAttr(int p) : Attr(Constructor), priority(p) {} + + int getPriority() const { return priority; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Constructor; } + static bool classof(const ConstructorAttr *A) { return true; } +}; + +class DestructorAttr : public Attr { + int priority; +public: + DestructorAttr(int p) : Attr(Destructor), priority(p) {} + + int getPriority() const { return priority; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Destructor; } + static bool classof(const DestructorAttr *A) { return true; } +}; + +class IBOutletAttr : public Attr { +public: + IBOutletAttr() : Attr(IBOutletKind) {} + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBOutletKind; + } + static bool classof(const IBOutletAttr *A) { return true; } +}; + +class IBOutletCollectionAttr : public Attr { + const ObjCInterfaceDecl *D; +public: + IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) + : Attr(IBOutletCollectionKind), D(d) {} + + const ObjCInterfaceDecl *getClass() const { return D; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBOutletCollectionKind; + } + static bool classof(const IBOutletCollectionAttr *A) { return true; } +}; + +class IBActionAttr : public Attr { +public: + IBActionAttr() : Attr(IBActionKind) {} + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBActionKind; + } + static bool classof(const IBActionAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(AnalyzerNoReturn); +DEF_SIMPLE_ATTR(Deprecated); +DEF_SIMPLE_ATTR(Final); +DEF_SIMPLE_ATTR(GNUInline); +DEF_SIMPLE_ATTR(Malloc); +DEF_SIMPLE_ATTR(NoReturn); + +class SectionAttr : public AttrWithString { +public: + SectionAttr(ASTContext &C, llvm::StringRef N) + : AttrWithString(Section, C, N) {} + + llvm::StringRef getName() const { return getString(); } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == Section; + } + static bool classof(const SectionAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(Unavailable); +DEF_SIMPLE_ATTR(Unused); +DEF_SIMPLE_ATTR(Used); +DEF_SIMPLE_ATTR(Weak); +DEF_SIMPLE_ATTR(WeakImport); +DEF_SIMPLE_ATTR(WeakRef); +DEF_SIMPLE_ATTR(NoThrow); +DEF_SIMPLE_ATTR(Const); +DEF_SIMPLE_ATTR(Pure); + +class NonNullAttr : public Attr { + unsigned* ArgNums; + unsigned Size; +public: + NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0); + + virtual void Destroy(ASTContext &C); + + typedef const unsigned *iterator; + iterator begin() const { return ArgNums; } + iterator end() const { return ArgNums + Size; } + unsigned size() const { return Size; } + + bool isNonNull(unsigned arg) const { + return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true; + } + + virtual Attr *clone(ASTContext &C) const; + + static bool classof(const Attr *A) { return A->getKind() == NonNull; } + static bool classof(const NonNullAttr *A) { return true; } +}; + +class FormatAttr : public AttrWithString { + int formatIdx, firstArg; +public: + FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first) + : AttrWithString(Format, C, type), formatIdx(idx), firstArg(first) {} + + llvm::StringRef getType() const { return getString(); } + void setType(ASTContext &C, llvm::StringRef type); + int getFormatIdx() const { return formatIdx; } + int getFirstArg() const { return firstArg; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Format; } + static bool classof(const FormatAttr *A) { return true; } +}; + +class FormatArgAttr : public Attr { + int formatIdx; +public: + FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {} + int getFormatIdx() const { return formatIdx; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == FormatArg; } + static bool classof(const FormatArgAttr *A) { return true; } +}; + +class SentinelAttr : public Attr { + int sentinel, NullPos; +public: + SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel), + sentinel(sentinel_val), NullPos(nullPos) {} + int getSentinel() const { return sentinel; } + int getNullPos() const { return NullPos; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Sentinel; } + static bool classof(const SentinelAttr *A) { return true; } +}; + +class VisibilityAttr : public Attr { +public: + /// @brief An enumeration for the kinds of visibility of symbols. + enum VisibilityTypes { + DefaultVisibility = 0, + HiddenVisibility, + ProtectedVisibility + }; +private: + VisibilityTypes VisibilityType; +public: + VisibilityAttr(VisibilityTypes v) : Attr(Visibility), + VisibilityType(v) {} + + VisibilityTypes getVisibility() const { return VisibilityType; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Visibility; } + static bool classof(const VisibilityAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(FastCall); +DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(ThisCall); +DEF_SIMPLE_ATTR(CDecl); +DEF_SIMPLE_ATTR(TransparentUnion); +DEF_SIMPLE_ATTR(ObjCNSObject); +DEF_SIMPLE_ATTR(ObjCException); + +class OverloadableAttr : public Attr { +public: + OverloadableAttr() : Attr(Overloadable) { } + + virtual bool isMerged() const { return false; } + + virtual Attr *clone(ASTContext &C) const; + + static bool classof(const Attr *A) { return A->getKind() == Overloadable; } + static bool classof(const OverloadableAttr *) { return true; } +}; + +class BlocksAttr : public Attr { +public: + enum BlocksAttrTypes { + ByRef = 0 + }; +private: + BlocksAttrTypes BlocksAttrType; +public: + BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {} + + BlocksAttrTypes getType() const { return BlocksAttrType; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Blocks; } + static bool classof(const BlocksAttr *A) { return true; } +}; + +class FunctionDecl; + +class CleanupAttr : public Attr { + FunctionDecl *FD; + +public: + CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {} + + const FunctionDecl *getFunctionDecl() const { return FD; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Cleanup; } + static bool classof(const CleanupAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(NoDebug); +DEF_SIMPLE_ATTR(WarnUnusedResult); +DEF_SIMPLE_ATTR(NoInline); + +class RegparmAttr : public Attr { + unsigned NumParams; + +public: + RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {} + + unsigned getNumParams() const { return NumParams; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == Regparm; } + static bool classof(const RegparmAttr *A) { return true; } +}; + +class ReqdWorkGroupSizeAttr : public Attr { + unsigned X, Y, Z; +public: + ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z) + : Attr(ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {} + + unsigned getXDim() const { return X; } + unsigned getYDim() const { return Y; } + unsigned getZDim() const { return Z; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == ReqdWorkGroupSize; + } + static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; } +}; + +// Checker-specific attributes. +DEF_SIMPLE_ATTR(CFReturnsNotRetained); +DEF_SIMPLE_ATTR(CFReturnsRetained); +DEF_SIMPLE_ATTR(NSReturnsNotRetained); +DEF_SIMPLE_ATTR(NSReturnsRetained); + +// C++0x member checking attributes. +DEF_SIMPLE_ATTR(BaseCheck); +DEF_SIMPLE_ATTR(Hiding); +DEF_SIMPLE_ATTR(Override); + +// Target-specific attributes +DEF_SIMPLE_ATTR(DLLImport); +DEF_SIMPLE_ATTR(DLLExport); + +class MSP430InterruptAttr : public Attr { + unsigned Number; + +public: + MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {} + + unsigned getNumber() const { return Number; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; } + static bool classof(const MSP430InterruptAttr *A) { return true; } +}; + +DEF_SIMPLE_ATTR(X86ForceAlignArgPointer); + +#undef DEF_SIMPLE_ATTR + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/CMakeLists.txt b/contrib/llvm/tools/clang/include/clang/AST/CMakeLists.txt new file mode 100644 index 0000000..c24ea06 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_TARGET_DEFINITIONS StmtNodes.td) +tablegen(StmtNodes.inc + -gen-clang-stmt-nodes) +add_custom_target(ClangStmtNodes + DEPENDS StmtNodes.inc) diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h new file mode 100644 index 0000000..5a84e40 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h @@ -0,0 +1,365 @@ +//===------ CXXInheritance.h - C++ Inheritance ------------------*- 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 routines that help analyzing C++ inheritance hierarchies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H +#define LLVM_CLANG_AST_CXXINHERITANCE_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeOrdering.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include <list> +#include <map> +#include <cassert> + +namespace clang { + +class CXXBaseSpecifier; +class CXXMethodDecl; +class CXXRecordDecl; +class NamedDecl; + +/// \brief Represents an element in a path from a derived class to a +/// base class. +/// +/// Each step in the path references the link from a +/// derived class to one of its direct base classes, along with a +/// base "number" that identifies which base subobject of the +/// original derived class we are referencing. +struct CXXBasePathElement { + /// \brief The base specifier that states the link from a derived + /// class to a base class, which will be followed by this base + /// path element. + const CXXBaseSpecifier *Base; + + /// \brief The record decl of the class that the base is a base of. + const CXXRecordDecl *Class; + + /// \brief Identifies which base class subobject (of type + /// \c Base->getType()) this base path element refers to. + /// + /// This value is only valid if \c !Base->isVirtual(), because there + /// is no base numbering for the zero or one virtual bases of a + /// given type. + int SubobjectNumber; +}; + +/// \brief Represents a path from a specific derived class +/// (which is not represented as part of the path) to a particular +/// (direct or indirect) base class subobject. +/// +/// Individual elements in the path are described by the \c CXXBasePathElement +/// structure, which captures both the link from a derived class to one of its +/// direct bases and identification describing which base class +/// subobject is being used. +class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { +public: + CXXBasePath() : Access(AS_public) {} + + /// \brief The access along this inheritance path. This is only + /// calculated when recording paths. AS_none is a special value + /// used to indicate a path which permits no legal access. + AccessSpecifier Access; + + /// \brief The set of declarations found inside this base class + /// subobject. + DeclContext::lookup_result Decls; + + void clear() { + llvm::SmallVectorImpl<CXXBasePathElement>::clear(); + Access = AS_public; + } +}; + +/// BasePaths - Represents the set of paths from a derived class to +/// one of its (direct or indirect) bases. For example, given the +/// following class hierachy: +/// +/// @code +/// class A { }; +/// class B : public A { }; +/// class C : public A { }; +/// class D : public B, public C{ }; +/// @endcode +/// +/// There are two potential BasePaths to represent paths from D to a +/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0) +/// and another is (D,0)->(C,0)->(A,1). These two paths actually +/// refer to two different base class subobjects of the same type, +/// so the BasePaths object refers to an ambiguous path. On the +/// other hand, consider the following class hierarchy: +/// +/// @code +/// class A { }; +/// class B : public virtual A { }; +/// class C : public virtual A { }; +/// class D : public B, public C{ }; +/// @endcode +/// +/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0) +/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them +/// refer to the same base class subobject of type A (the virtual +/// one), there is no ambiguity. +class CXXBasePaths { + /// \brief The type from which this search originated. + CXXRecordDecl *Origin; + + /// Paths - The actual set of paths that can be taken from the + /// derived class to the same base class. + std::list<CXXBasePath> Paths; + + /// ClassSubobjects - Records the class subobjects for each class + /// type that we've seen. The first element in the pair says + /// whether we found a path to a virtual base for that class type, + /// while the element contains the number of non-virtual base + /// class subobjects for that class type. The key of the map is + /// the cv-unqualified canonical type of the base class subobject. + std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering> + ClassSubobjects; + + /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find + /// ambiguous paths while it is looking for a path from a derived + /// type to a base type. + bool FindAmbiguities; + + /// RecordPaths - Whether Sema::IsDerivedFrom should record paths + /// while it is determining whether there are paths from a derived + /// type to a base type. + bool RecordPaths; + + /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search + /// if it finds a path that goes across a virtual base. The virtual class + /// is also recorded. + bool DetectVirtual; + + /// ScratchPath - A BasePath that is used by Sema::lookupInBases + /// to help build the set of paths. + CXXBasePath ScratchPath; + + /// DetectedVirtual - The base class that is virtual. + const RecordType *DetectedVirtual; + + /// \brief Array of the declarations that have been found. This + /// array is constructed only if needed, e.g., to iterate over the + /// results within LookupResult. + NamedDecl **DeclsFound; + unsigned NumDeclsFound; + + friend class CXXRecordDecl; + + void ComputeDeclsFound(); + + bool lookupInBases(ASTContext &Context, + const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback *BaseMatches, + void *UserData); +public: + typedef std::list<CXXBasePath>::iterator paths_iterator; + typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; + typedef NamedDecl **decl_iterator; + + /// BasePaths - Construct a new BasePaths structure to record the + /// paths for a derived-to-base search. + explicit CXXBasePaths(bool FindAmbiguities = true, + bool RecordPaths = true, + bool DetectVirtual = true) + : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), + DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0), + NumDeclsFound(0) { } + + ~CXXBasePaths() { delete [] DeclsFound; } + + paths_iterator begin() { return Paths.begin(); } + paths_iterator end() { return Paths.end(); } + const_paths_iterator begin() const { return Paths.begin(); } + const_paths_iterator end() const { return Paths.end(); } + + CXXBasePath& front() { return Paths.front(); } + const CXXBasePath& front() const { return Paths.front(); } + + decl_iterator found_decls_begin(); + decl_iterator found_decls_end(); + + /// \brief Determine whether the path from the most-derived type to the + /// given base type is ambiguous (i.e., it refers to multiple subobjects of + /// the same base type). + bool isAmbiguous(CanQualType BaseType); + + /// \brief Whether we are finding multiple paths to detect ambiguities. + bool isFindingAmbiguities() const { return FindAmbiguities; } + + /// \brief Whether we are recording paths. + bool isRecordingPaths() const { return RecordPaths; } + + /// \brief Specify whether we should be recording paths or not. + void setRecordingPaths(bool RP) { RecordPaths = RP; } + + /// \brief Whether we are detecting virtual bases. + bool isDetectingVirtual() const { return DetectVirtual; } + + /// \brief The virtual base discovered on the path (if we are merely + /// detecting virtuals). + const RecordType* getDetectedVirtual() const { + return DetectedVirtual; + } + + /// \brief Retrieve the type from which this base-paths search + /// began + CXXRecordDecl *getOrigin() const { return Origin; } + void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; } + + /// \brief Clear the base-paths results. + void clear(); + + /// \brief Swap this data structure's contents with another CXXBasePaths + /// object. + void swap(CXXBasePaths &Other); +}; + +/// \brief Uniquely identifies a virtual method within a class +/// hierarchy by the method itself and a class subobject number. +struct UniqueVirtualMethod { + UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { } + + UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, + const CXXRecordDecl *InVirtualSubobject) + : Method(Method), Subobject(Subobject), + InVirtualSubobject(InVirtualSubobject) { } + + /// \brief The overriding virtual method. + CXXMethodDecl *Method; + + /// \brief The subobject in which the overriding virtual method + /// resides. + unsigned Subobject; + + /// \brief The virtual base class subobject of which this overridden + /// virtual method is a part. Note that this records the closest + /// derived virtual base class subobject. + const CXXRecordDecl *InVirtualSubobject; + + friend bool operator==(const UniqueVirtualMethod &X, + const UniqueVirtualMethod &Y) { + return X.Method == Y.Method && X.Subobject == Y.Subobject && + X.InVirtualSubobject == Y.InVirtualSubobject; + } + + friend bool operator!=(const UniqueVirtualMethod &X, + const UniqueVirtualMethod &Y) { + return !(X == Y); + } +}; + +/// \brief The set of methods that override a given virtual method in +/// each subobject where it occurs. +/// +/// The first part of the pair is the subobject in which the +/// overridden virtual function occurs, while the second part of the +/// pair is the virtual method that overrides it (including the +/// subobject in which that virtual function occurs). +class OverridingMethods { + llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + Overrides; + +public: + // Iterate over the set of subobjects that have overriding methods. + typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + ::iterator iterator; + typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + ::const_iterator const_iterator; + iterator begin() { return Overrides.begin(); } + const_iterator begin() const { return Overrides.begin(); } + iterator end() { return Overrides.end(); } + const_iterator end() const { return Overrides.end(); } + unsigned size() const { return Overrides.size(); } + + // Iterate over the set of overriding virtual methods in a given + // subobject. + typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator + overriding_iterator; + typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator + overriding_const_iterator; + + // Add a new overriding method for a particular subobject. + void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding); + + // Add all of the overriding methods from "other" into overrides for + // this method. Used when merging the overrides from multiple base + // class subobjects. + void add(const OverridingMethods &Other); + + // Replace all overriding virtual methods in all subobjects with the + // given virtual method. + void replaceAll(UniqueVirtualMethod Overriding); +}; + +/// \brief A mapping from each virtual member function to its set of +/// final overriders. +/// +/// Within a class hierarchy for a given derived class, each virtual +/// member function in that hierarchy has one or more "final +/// overriders" (C++ [class.virtual]p2). A final overrider for a +/// virtual function "f" is the virtual function that will actually be +/// invoked when dispatching a call to "f" through the +/// vtable. Well-formed classes have a single final overrider for each +/// virtual function; in abstract classes, the final overrider for at +/// least one virtual function is a pure virtual function. Due to +/// multiple, virtual inheritance, it is possible for a class to have +/// more than one final overrider. Athough this is an error (per C++ +/// [class.virtual]p2), it is not considered an error here: the final +/// overrider map can represent multiple final overriders for a +/// method, and it is up to the client to determine whether they are +/// problem. For example, the following class \c D has two final +/// overriders for the virtual function \c A::f(), one in \c C and one +/// in \c D: +/// +/// \code +/// struct A { virtual void f(); }; +/// struct B : virtual A { virtual void f(); }; +/// struct C : virtual A { virtual void f(); }; +/// struct D : B, C { }; +/// \endcode +/// +/// This data structure contaings a mapping from every virtual +/// function *that does not override an existing virtual function* and +/// in every subobject where that virtual function occurs to the set +/// of virtual functions that override it. Thus, the same virtual +/// function \c A::f can actually occur in multiple subobjects of type +/// \c A due to multiple inheritance, and may be overriden by +/// different virtual functions in each, as in the following example: +/// +/// \code +/// struct A { virtual void f(); }; +/// struct B : A { virtual void f(); }; +/// struct C : A { virtual void f(); }; +/// struct D : B, C { }; +/// \endcode +/// +/// Unlike in the previous example, where the virtual functions \c +/// B::f and \c C::f both overrode \c A::f in the same subobject of +/// type \c A, in this example the two virtual functions both override +/// \c A::f but in *different* subobjects of type A. This is +/// represented by numbering the subobjects in which the overridden +/// and the overriding virtual member functions are located. Subobject +/// 0 represents the virtua base class subobject of that type, while +/// subobject numbers greater than 0 refer to non-virtual base class +/// subobjects of that type. +class CXXFinalOverriderMap + : public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { }; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h new file mode 100644 index 0000000..4afb81d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h @@ -0,0 +1,742 @@ +//===-- CanonicalType.h - C Language Family Type Representation -*- 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 CanQual class template, which provides access to +// canonical types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H +#define LLVM_CLANG_AST_CANONICAL_TYPE_H + +#include "clang/AST/Type.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/type_traits.h" +#include <iterator> + +namespace clang { + +template<typename T> class CanProxy; +template<typename T> struct CanProxyAdaptor; + +//----------------------------------------------------------------------------// +// Canonical, qualified type template +//----------------------------------------------------------------------------// + +/// \brief Represents a canonical, potentially-qualified type. +/// +/// The CanQual template is a lightweight smart pointer that provides access +/// to the canonical representation of a type, where all typedefs and other +/// syntactic sugar has been eliminated. A CanQualType may also have various +/// qualifiers (const, volatile, restrict) attached to it. +/// +/// The template type parameter @p T is one of the Type classes (PointerType, +/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that +/// type (or some subclass of that type). The typedef @c CanQualType is just +/// a shorthand for @c CanQual<Type>. +/// +/// An instance of @c CanQual<T> can be implicitly converted to a +/// @c CanQual<U> when T is derived from U, which essentially provides an +/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be +/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can +/// be implicitly converted to a QualType, but the reverse operation requires +/// a call to ASTContext::getCanonicalType(). +/// +/// +template<typename T = Type> +class CanQual { + /// \brief The actual, canonical type. + QualType Stored; + +public: + /// \brief Constructs a NULL canonical type. + CanQual() : Stored() { } + + /// \brief Converting constructor that permits implicit upcasting of + /// canonical type pointers. + template<typename U> + CanQual(const CanQual<U>& Other, + typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0); + + /// \brief Retrieve the underlying type pointer, which refers to a + /// canonical type. + T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); } + + /// \brief Implicit conversion to a qualified type. + operator QualType() const { return Stored; } + + /// \brief Implicit conversion to bool. + operator bool() const { return !isNull(); } + + bool isNull() const { + return Stored.isNull(); + } + + /// \brief Retrieve a canonical type pointer with a different static type, + /// upcasting or downcasting as needed. + /// + /// The getAs() function is typically used to try to downcast to a + /// more specific (canonical) type in the type system. For example: + /// + /// @code + /// void f(CanQual<Type> T) { + /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { + /// // look at Ptr's pointee type + /// } + /// } + /// @endcode + /// + /// \returns A proxy pointer to the same type, but with the specified + /// static type (@p U). If the dynamic type is not the specified static type + /// or a derived class thereof, a NULL canonical type. + template<typename U> CanProxy<U> getAs() const; + + /// \brief Overloaded arrow operator that produces a canonical type + /// proxy. + CanProxy<T> operator->() const; + + /// \brief Retrieve all qualifiers. + Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } + + /// \brief Retrieve the const/volatile/restrict qualifiers. + unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } + + /// \brief Determines whether this type has any qualifiers + bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } + + bool isConstQualified() const { + return Stored.isLocalConstQualified(); + } + bool isVolatileQualified() const { + return Stored.isLocalVolatileQualified(); + } + bool isRestrictQualified() const { + return Stored.isLocalRestrictQualified(); + } + + /// \brief Determines if this canonical type is furthermore + /// canonical as a parameter. The parameter-canonicalization + /// process decays arrays to pointers and drops top-level qualifiers. + bool isCanonicalAsParam() const { + return Stored.isCanonicalAsParam(); + } + + /// \brief Retrieve the unqualified form of this type. + CanQual<T> getUnqualifiedType() const; + + /// \brief Retrieves a version of this type with const applied. + /// Note that this does not always yield a canonical type. + QualType withConst() const { + return Stored.withConst(); + } + + /// \brief Determines whether this canonical type is more qualified than + /// the @p Other canonical type. + bool isMoreQualifiedThan(CanQual<T> Other) const { + return Stored.isMoreQualifiedThan(Other.Stored); + } + + /// \brief Determines whether this canonical type is at least as qualified as + /// the @p Other canonical type. + bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { + return Stored.isAtLeastAsQualifiedAs(Other.Stored); + } + + /// \brief If the canonical type is a reference type, returns the type that + /// it refers to; otherwise, returns the type itself. + CanQual<Type> getNonReferenceType() const; + + /// \brief Retrieve the internal representation of this canonical type. + void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } + + /// \brief Construct a canonical type from its internal representation. + static CanQual<T> getFromOpaquePtr(void *Ptr); + + /// \brief Builds a canonical type from a QualType. + /// + /// This routine is inherently unsafe, because it requires the user to + /// ensure that the given type is a canonical type with the correct + // (dynamic) type. + static CanQual<T> CreateUnsafe(QualType Other); + + void dump() const { Stored.dump(); } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(getAsOpaquePtr()); + } +}; + +template<typename T, typename U> +inline bool operator==(CanQual<T> x, CanQual<U> y) { + return x.getAsOpaquePtr() == y.getAsOpaquePtr(); +} + +template<typename T, typename U> +inline bool operator!=(CanQual<T> x, CanQual<U> y) { + return x.getAsOpaquePtr() != y.getAsOpaquePtr(); +} + +/// \brief Represents a canonical, potentially-qualified type. +typedef CanQual<Type> CanQualType; + +inline CanQualType Type::getCanonicalTypeUnqualified() const { + return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + CanQualType T) { + DB << static_cast<QualType>(T); + return DB; +} + +//----------------------------------------------------------------------------// +// Internal proxy classes used by canonical types +//----------------------------------------------------------------------------// + +#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ +CanQualType Accessor() const { \ +return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ +} + +#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ +Type Accessor() const { return this->getTypePtr()->Accessor(); } + +/// \brief Base class of all canonical proxy types, which is responsible for +/// storing the underlying canonical type and providing basic conversions. +template<typename T> +class CanProxyBase { +protected: + CanQual<T> Stored; + +public: + /// \brief Retrieve the pointer to the underlying Type + T* getTypePtr() const { return Stored.getTypePtr(); } + + /// \brief Implicit conversion to the underlying pointer. + /// + /// Also provides the ability to use canonical type proxies in a Boolean + // context,e.g., + /// @code + /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } + /// @endcode + operator const T*() const { return this->Stored.getTypePtr(); } + + /// \brief Try to convert the given canonical type to a specific structural + /// type. + template<typename U> CanProxy<U> getAs() const { + return this->Stored.template getAs<U>(); + } + + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) + + // Type predicates + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) + + /// \brief Retrieve the proxy-adaptor type. + /// + /// This arrow operator is used when CanProxyAdaptor has been specialized + /// for the given type T. In that case, we reference members of the + /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden + /// by the arrow operator in the primary CanProxyAdaptor template. + const CanProxyAdaptor<T> *operator->() const { + return static_cast<const CanProxyAdaptor<T> *>(this); + } +}; + +/// \brief Replacable canonical proxy adaptor class that provides the link +/// between a canonical type and the accessors of the type. +/// +/// The CanProxyAdaptor is a replaceable class template that is instantiated +/// as part of each canonical proxy type. The primary template merely provides +/// redirection to the underlying type (T), e.g., @c PointerType. One can +/// provide specializations of this class template for each underlying type +/// that provide accessors returning canonical types (@c CanQualType) rather +/// than the more typical @c QualType, to propagate the notion of "canonical" +/// through the system. +template<typename T> +struct CanProxyAdaptor : CanProxyBase<T> { }; + +/// \brief Canonical proxy type returned when retrieving the members of a +/// canonical type or as the result of the @c CanQual<T>::getAs member +/// function. +/// +/// The CanProxy type mainly exists as a proxy through which operator-> will +/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy +/// type that provides canonical-type access to the fields of the type. +template<typename T> +class CanProxy : public CanProxyAdaptor<T> { +public: + /// \brief Build a NULL proxy. + CanProxy() { } + + /// \brief Build a proxy to the given canonical type. + CanProxy(CanQual<T> Stored) { this->Stored = Stored; } + + /// \brief Implicit conversion to the stored canonical type. + operator CanQual<T>() const { return this->Stored; } +}; + +} // end namespace clang + +namespace llvm { + +/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from +/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. +/// to return smart pointer (proxies?). +template<typename T> +struct simplify_type<const ::clang::CanQual<T> > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) { + return Val.getTypePtr(); + } +}; +template<typename T> +struct simplify_type< ::clang::CanQual<T> > +: public simplify_type<const ::clang::CanQual<T> > {}; + +// Teach SmallPtrSet that CanQual<T> is "basically a pointer". +template<typename T> +class PointerLikeTypeTraits<clang::CanQual<T> > { +public: + static inline void *getAsVoidPointer(clang::CanQual<T> P) { + return P.getAsOpaquePtr(); + } + static inline clang::CanQual<T> getFromVoidPointer(void *P) { + return clang::CanQual<T>::getFromOpaquePtr(P); + } + // qualifier information is encoded in the low bits. + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +namespace clang { + +//----------------------------------------------------------------------------// +// Canonical proxy adaptors for canonical type nodes. +//----------------------------------------------------------------------------// + +/// \brief Iterator adaptor that turns an iterator over canonical QualTypes +/// into an iterator over CanQualTypes. +template<typename InputIterator> +class CanTypeIterator { + InputIterator Iter; + +public: + typedef CanQualType value_type; + typedef value_type reference; + typedef CanProxy<Type> pointer; + typedef typename std::iterator_traits<InputIterator>::difference_type + difference_type; + typedef typename std::iterator_traits<InputIterator>::iterator_category + iterator_category; + + CanTypeIterator() : Iter() { } + explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { } + + // Input iterator + reference operator*() const { + return CanQualType::CreateUnsafe(*Iter); + } + + pointer operator->() const; + + CanTypeIterator &operator++() { + ++Iter; + return *this; + } + + CanTypeIterator operator++(int) { + CanTypeIterator Tmp(*this); + ++Iter; + return Tmp; + } + + friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) { + return X.Iter == Y.Iter; + } + friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) { + return X.Iter != Y.Iter; + } + + // Bidirectional iterator + CanTypeIterator &operator--() { + --Iter; + return *this; + } + + CanTypeIterator operator--(int) { + CanTypeIterator Tmp(*this); + --Iter; + return Tmp; + } + + // Random access iterator + reference operator[](difference_type n) const { + return CanQualType::CreateUnsafe(Iter[n]); + } + + CanTypeIterator &operator+=(difference_type n) { + Iter += n; + return *this; + } + + CanTypeIterator &operator-=(difference_type n) { + Iter -= n; + return *this; + } + + friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) { + X += n; + return X; + } + + friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) { + X += n; + return X; + } + + friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) { + X -= n; + return X; + } + + friend difference_type operator-(const CanTypeIterator &X, + const CanTypeIterator &Y) { + return X - Y; + } +}; + +template<> +struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) +}; + +template<> +struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<BlockPointerType> + : public CanProxyBase<BlockPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<LValueReferenceType> + : public CanProxyBase<LValueReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<RValueReferenceType> + : public CanProxyBase<RValueReferenceType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) +}; + +template<> +struct CanProxyAdaptor<MemberPointerType> + : public CanProxyBase<MemberPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) +}; + +template<> +struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) +}; + +template<> +struct CanProxyAdaptor<ConstantArrayType> + : public CanProxyBase<ConstantArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) +}; + +template<> +struct CanProxyAdaptor<IncompleteArrayType> + : public CanProxyBase<IncompleteArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) +}; + +template<> +struct CanProxyAdaptor<VariableArrayType> + : public CanProxyBase<VariableArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, + getSizeModifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) +}; + +template<> +struct CanProxyAdaptor<DependentSizedArrayType> + : public CanProxyBase<DependentSizedArrayType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) +}; + +template<> +struct CanProxyAdaptor<DependentSizedExtVectorType> + : public CanProxyBase<DependentSizedExtVectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) +}; + +template<> +struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) +}; + +template<> +struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) +}; + +template<> +struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) +}; + +template<> +struct CanProxyAdaptor<FunctionNoProtoType> + : public CanProxyBase<FunctionNoProtoType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) +}; + +template<> +struct CanProxyAdaptor<FunctionProtoType> + : public CanProxyBase<FunctionProtoType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs) + CanQualType getArgType(unsigned i) const { + return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); + } + + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) + + typedef CanTypeIterator<FunctionProtoType::arg_type_iterator> + arg_type_iterator; + + arg_type_iterator arg_type_begin() const { + return arg_type_iterator(this->getTypePtr()->arg_type_begin()); + } + + arg_type_iterator arg_type_end() const { + return arg_type_iterator(this->getTypePtr()->arg_type_end()); + } + + // Note: canonical function types never have exception specifications +}; + +template<> +struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) +}; + +template<> +struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) +}; + +template<> +struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) +}; + +template<> +struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace) +}; + +template<> +struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) +}; + +template<> +struct CanProxyAdaptor<TemplateTypeParmType> + : public CanProxyBase<TemplateTypeParmType> { + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) +}; + +template<> +struct CanProxyAdaptor<ObjCObjectType> + : public CanProxyBase<ObjCObjectType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, + getInterface) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + +template<> +struct CanProxyAdaptor<ObjCObjectPointerType> + : public CanProxyBase<ObjCObjectPointerType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, + getInterfaceType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + +//----------------------------------------------------------------------------// +// Method and function definitions +//----------------------------------------------------------------------------// +template<typename T> +inline CanQual<T> CanQual<T>::getUnqualifiedType() const { + return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); +} + +template<typename T> +inline CanQual<Type> CanQual<T>::getNonReferenceType() const { + if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) + return RefType->getPointeeType(); + else + return *this; +} + +template<typename T> +CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { + CanQual<T> Result; + Result.Stored.setFromOpaqueValue(Ptr); + assert((!Result || Result.Stored.isCanonical()) + && "Type is not canonical!"); + return Result; +} + +template<typename T> +CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { + assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); + assert((Other.isNull() || isa<T>(Other.getTypePtr())) && + "Dynamic type does not meet the static type's requires"); + CanQual<T> Result; + Result.Stored = Other; + return Result; +} + +template<typename T> +template<typename U> +CanProxy<U> CanQual<T>::getAs() const { + if (Stored.isNull()) + return CanProxy<U>(); + + if (isa<U>(Stored.getTypePtr())) + return CanQual<U>::CreateUnsafe(Stored); + + return CanProxy<U>(); +} + +template<typename T> +CanProxy<T> CanQual<T>::operator->() const { + return CanProxy<T>(*this); +} + +template<typename InputIterator> +typename CanTypeIterator<InputIterator>::pointer +CanTypeIterator<InputIterator>::operator->() const { + return CanProxy<Type>(*this); +} + +} + + +#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h new file mode 100644 index 0000000..0bb4b76 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h @@ -0,0 +1,149 @@ +//===--- CharUnits.h - Character units for sizes and offsets ----*- 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 CharUnits class +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CHARUNITS_H +#define LLVM_CLANG_AST_CHARUNITS_H + +#include "llvm/System/DataTypes.h" + +namespace clang { + + /// CharUnits - This is an opaque type for sizes expressed in character units. + /// Instances of this type represent a quantity as a multiple of the size + /// of the standard C type, char, on the target architecture. As an opaque + /// type, CharUnits protects you from accidentally combining operations on + /// quantities in bit units and character units. + /// + /// It should be noted that characters and bytes are distinct concepts. Bytes + /// refer to addressable units of data storage on the target machine, and + /// characters are members of a set of elements used for the organization, + /// control, or representation of data. According to C99, bytes are allowed + /// to exceed characters in size, although currently, clang only supports + /// architectures where the two are the same size. + /// + /// For portability, never assume that a target character is 8 bits wide. Use + /// CharUnit values whereever you calculate sizes, offsets, or alignments + /// in character units. + class CharUnits { + public: + typedef int64_t QuantityType; + + private: + QuantityType Quantity; + + explicit CharUnits(QuantityType C) : Quantity(C) {} + + public: + + /// CharUnits - A default constructor. + CharUnits() : Quantity(0) {} + + /// Zero - Construct a CharUnits quantity of zero. + static CharUnits Zero() { + return CharUnits(0); + } + + /// One - Construct a CharUnits quantity of one. + static CharUnits One() { + return CharUnits(1); + } + + /// fromQuantity - Construct a CharUnits quantity from a raw integer type. + static CharUnits fromQuantity(QuantityType Quantity) { + return CharUnits(Quantity); + } + + // Compound assignment. + CharUnits& operator+= (const CharUnits &Other) { + Quantity += Other.Quantity; + return *this; + } + CharUnits& operator-= (const CharUnits &Other) { + Quantity -= Other.Quantity; + return *this; + } + + // Comparison operators. + bool operator== (const CharUnits &Other) const { + return Quantity == Other.Quantity; + } + bool operator!= (const CharUnits &Other) const { + return Quantity != Other.Quantity; + } + + // Relational operators. + bool operator< (const CharUnits &Other) const { + return Quantity < Other.Quantity; + } + bool operator<= (const CharUnits &Other) const { + return Quantity <= Other.Quantity; + } + bool operator> (const CharUnits &Other) const { + return Quantity > Other.Quantity; + } + bool operator>= (const CharUnits &Other) const { + return Quantity >= Other.Quantity; + } + + // Other predicates. + + /// isZero - Test whether the quantity equals zero. + bool isZero() const { return Quantity == 0; } + + /// isOne - Test whether the quantity equals one. + bool isOne() const { return Quantity == 1; } + + /// isPositive - Test whether the quantity is greater than zero. + bool isPositive() const { return Quantity > 0; } + + /// isNegative - Test whether the quantity is less than zero. + bool isNegative() const { return Quantity < 0; } + + // Arithmetic operators. + CharUnits operator* (QuantityType N) const { + return CharUnits(Quantity * N); + } + CharUnits operator/ (QuantityType N) const { + return CharUnits(Quantity / N); + } + QuantityType operator/ (const CharUnits &Other) const { + return Quantity / Other.Quantity; + } + CharUnits operator% (QuantityType N) const { + return CharUnits(Quantity % N); + } + QuantityType operator% (const CharUnits &Other) const { + return Quantity % Other.Quantity; + } + CharUnits operator+ (const CharUnits &Other) const { + return CharUnits(Quantity + Other.Quantity); + } + CharUnits operator- (const CharUnits &Other) const { + return CharUnits(Quantity - Other.Quantity); + } + + // Conversions. + + /// getQuantity - Get the raw integer representation of this quantity. + QuantityType getQuantity() const { return Quantity; } + + + }; // class CharUnit +} // namespace clang + +inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale, + const clang::CharUnits &CU) { + return CU * Scale; +} + +#endif // LLVM_CLANG_AST_CHARUNITS_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h new file mode 100644 index 0000000..7d5b66e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h @@ -0,0 +1,2196 @@ +//===--- Decl.h - Classes for representing declarations ---------*- 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 Decl subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECL_H +#define LLVM_CLANG_AST_DECL_H + +#include "clang/AST/APValue.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Redeclarable.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/Linkage.h" + +namespace clang { +class CXXTemporary; +class Expr; +class FunctionTemplateDecl; +class Stmt; +class CompoundStmt; +class StringLiteral; +class TemplateArgumentList; +class MemberSpecializationInfo; +class FunctionTemplateSpecializationInfo; +class DependentFunctionTemplateSpecializationInfo; +class TypeLoc; +class UnresolvedSetImpl; + +/// \brief A container of type source information. +/// +/// A client can read the relevant info using TypeLoc wrappers, e.g: +/// @code +/// TypeLoc TL = TypeSourceInfo->getTypeLoc(); +/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL)) +/// PL->getStarLoc().print(OS, SrcMgr); +/// @endcode +/// +class TypeSourceInfo { + QualType Ty; + // Contains a memory block after the class, used for type source information, + // allocated by ASTContext. + friend class ASTContext; + TypeSourceInfo(QualType ty) : Ty(ty) { } +public: + /// \brief Return the type wrapped by this type source info. + QualType getType() const { return Ty; } + + /// \brief Return the TypeLoc wrapper for the type source info. + TypeLoc getTypeLoc() const; // implemented in TypeLoc.h +}; + +/// TranslationUnitDecl - The top declaration context. +class TranslationUnitDecl : public Decl, public DeclContext { + ASTContext &Ctx; + + /// The (most recently entered) anonymous namespace for this + /// translation unit, if one has been created. + NamespaceDecl *AnonymousNamespace; + + explicit TranslationUnitDecl(ASTContext &ctx) + : Decl(TranslationUnit, 0, SourceLocation()), + DeclContext(TranslationUnit), + Ctx(ctx), AnonymousNamespace(0) {} +public: + ASTContext &getASTContext() const { return Ctx; } + + NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } + void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } + + static TranslationUnitDecl *Create(ASTContext &C); + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TranslationUnitDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TranslationUnit; } + static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { + return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D)); + } + static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// NamedDecl - This represents a decl with a name. Many decls have names such +/// as ObjCMethodDecl, but not @class, etc. +class NamedDecl : public Decl { + /// 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; + +protected: + NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) + : Decl(DK, DC, L), Name(N) { } + +public: + /// getIdentifier - Get the identifier that names this declaration, + /// if there is one. This will return NULL if this declaration has + /// no name (e.g., for an unnamed class) or if the name is a special + /// name (C++ constructor, Objective-C selector, etc.). + IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } + + /// getName - Get the name of identifier for this declaration as a StringRef. + /// This requires that the declaration have a name and that it be a simple + /// identifier. + llvm::StringRef getName() const { + assert(Name.isIdentifier() && "Name is not a simple identifier"); + return getIdentifier() ? getIdentifier()->getName() : ""; + } + + /// getNameAsCString - Get the name of identifier for this declaration as a + /// C string (const char*). This requires that the declaration have a name + /// and that it be a simple identifier. + // + // FIXME: Deprecated, move clients to getName(). + const char *getNameAsCString() const { + assert(Name.isIdentifier() && "Name is not a simple identifier"); + return getIdentifier() ? getIdentifier()->getNameStart() : ""; + } + + /// getNameAsString - Get a human-readable name for the declaration, even if + /// it is one of the special kinds of names (C++ constructor, Objective-C + /// selector, etc). Creating this name requires expensive string + /// manipulation, so it should be called only when performance doesn't matter. + /// For simple declarations, getNameAsCString() should suffice. + // + // FIXME: This function should be renamed to indicate that it is not just an + // alternate form of getName(), and clients should move as appropriate. + // + // FIXME: Deprecated, move clients to getName(). + std::string getNameAsString() const { return Name.getAsString(); } + + void printName(llvm::raw_ostream &os) const { return Name.printName(os); } + + /// getDeclName - Get the actual, stored name of the declaration, + /// which may be a special name. + DeclarationName getDeclName() const { return Name; } + + /// \brief Set the name of this declaration. + void setDeclName(DeclarationName N) { Name = N; } + + /// getQualifiedNameAsString - Returns human-readable qualified name for + /// declaration, like A::B::i, for i being member of namespace A::B. + /// If declaration is not member of context which can be named (record, + /// namespace), it will return same result as getNameAsString(). + /// Creating this name is expensive, so it should be called only when + /// performance doesn't matter. + std::string getQualifiedNameAsString() const; + std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const; + + /// getNameForDiagnostic - Appends a human-readable name for this + /// declaration into the given string. + /// + /// This is the method invoked by Sema when displaying a NamedDecl + /// in a diagnostic. It does not necessarily produce the same + /// result as getNameAsString(); for example, class template + /// specializations are printed with their template arguments. + /// + /// TODO: use an API that doesn't require so many temporary strings + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const { + if (Qualified) + S += getQualifiedNameAsString(Policy); + else + S += getNameAsString(); + } + + /// declarationReplaces - Determine whether this declaration, if + /// known to be well-formed within its context, will replace the + /// declaration OldD if introduced into scope. A declaration will + /// replace another declaration if, for example, it is a + /// redeclaration of the same variable or function, but not if it is + /// a declaration of a different kind (function vs. class) or an + /// overloaded function. + bool declarationReplaces(NamedDecl *OldD) const; + + /// \brief Determine whether this declaration has linkage. + bool hasLinkage() const; + + /// \brief Determine whether this declaration is a C++ class member. + bool isCXXClassMember() const { + const DeclContext *DC = getDeclContext(); + + // C++0x [class.mem]p1: + // The enumerators of an unscoped enumeration defined in + // the class are members of the class. + // FIXME: support C++0x scoped enumerations. + if (isa<EnumDecl>(DC)) + DC = DC->getParent(); + + return DC->isRecord(); + } + + /// \brief Given that this declaration is a C++ class member, + /// determine whether it's an instance member of its class. + bool isCXXInstanceMember() const; + + /// \brief Determine what kind of linkage this entity has. + Linkage getLinkage() const; + + /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for + /// the underlying named decl. + NamedDecl *getUnderlyingDecl(); + const NamedDecl *getUnderlyingDecl() const { + return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const NamedDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; } +}; + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const NamedDecl *ND) { + ND->getDeclName().printName(OS); + return OS; +} + +/// NamespaceDecl - Represent a C++ namespace. +class NamespaceDecl : public NamedDecl, public DeclContext { + SourceLocation LBracLoc, RBracLoc; + + // 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 itself. + NamespaceDecl *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 L, IdentifierInfo *Id) + : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), + NextNamespace(0), OrigOrAnonNamespace(0, true) { } + +public: + static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id); + + virtual void Destroy(ASTContext& C); + + // \brief Returns true if this is an anonymous namespace declaration. + // + // For example: + /// \code + // namespace { + // ... + // }; + // \endcode + // q.v. C++ [namespace.unnamed] + bool isAnonymousNamespace() const { + return !getIdentifier(); + } + + /// \brief Return the next extended namespace declaration or null if this + /// is none. + NamespaceDecl *getNextNamespace() { return NextNamespace; } + const NamespaceDecl *getNextNamespace() const { return NextNamespace; } + + /// \brief Set the next extended namespace declaration. + void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + + /// \brief Get the original (first) namespace declaration. + NamespaceDecl *getOriginalNamespace() const { + if (OrigOrAnonNamespace.getInt()) + return const_cast<NamespaceDecl *>(this); + + return OrigOrAnonNamespace.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); + } + } + + NamespaceDecl *getAnonymousNamespace() const { + return getOriginalNamespace()->OrigOrAnonNamespace.getPointer(); + } + + void setAnonymousNamespace(NamespaceDecl *D) { + assert(!D || D->isAnonymousNamespace()); + assert(!D || D->getParent() == this); + getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); + } + + virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } + const NamespaceDecl *getCanonicalDecl() const { + return getOriginalNamespace(); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), RBracLoc); + } + + SourceLocation getLBracLoc() const { return LBracLoc; } + SourceLocation getRBracLoc() const { return RBracLoc; } + void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; } + void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const NamespaceDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Namespace; } + static DeclContext *castToDeclContext(const NamespaceDecl *D) { + return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D)); + } + static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// ValueDecl - Represent the declaration of a variable (in which case it is +/// an lvalue) a function (in which case it is a function designator) or +/// an enum constant. +class ValueDecl : public NamedDecl { + QualType DeclType; + +protected: + ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T) + : NamedDecl(DK, DC, L, N), DeclType(T) {} +public: + QualType getType() const { return DeclType; } + void setType(QualType newType) { DeclType = newType; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ValueDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= ValueFirst && K <= ValueLast; } +}; + +/// \brief Represents a ValueDecl that came out of a declarator. +/// Contains type source information through TypeSourceInfo. +class DeclaratorDecl : public ValueDecl { + // A struct representing both a TInfo and a syntactic qualifier, + // to be used for the (uncommon) case of out-of-line declarations. + struct ExtInfo { + TypeSourceInfo *TInfo; + NestedNameSpecifier *NNS; + SourceRange NNSRange; + }; + + llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; + + bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } + ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } + const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); } + +protected: + DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo) + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} + +public: + virtual ~DeclaratorDecl(); + virtual void Destroy(ASTContext &C); + + TypeSourceInfo *getTypeSourceInfo() const { + return hasExtInfo() + ? DeclInfo.get<ExtInfo*>()->TInfo + : DeclInfo.get<TypeSourceInfo*>(); + } + void setTypeSourceInfo(TypeSourceInfo *TI) { + if (hasExtInfo()) + DeclInfo.get<ExtInfo*>()->TInfo = TI; + else + DeclInfo = TI; + } + + NestedNameSpecifier *getQualifier() const { + return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0; + } + SourceRange getQualifierRange() const { + return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange(); + } + void setQualifierInfo(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange); + + SourceLocation getTypeSpecStartLoc() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const DeclaratorDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= DeclaratorFirst && K <= DeclaratorLast; + } +}; + +/// \brief Structure used to store a statement, the constant value to +/// which it was evaluated (if any), and whether or not the statement +/// is an integral constant expression (if known). +struct EvaluatedStmt { + EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), + CheckingICE(false), IsICE(false) { } + + /// \brief Whether this statement was already evaluated. + bool WasEvaluated : 1; + + /// \brief Whether this statement is being evaluated. + bool IsEvaluating : 1; + + /// \brief Whether we already checked whether this statement was an + /// integral constant expression. + bool CheckedICE : 1; + + /// \brief Whether we are checking whether this statement is an + /// integral constant expression. + bool CheckingICE : 1; + + /// \brief Whether this statement is an integral constant + /// expression. Only valid if CheckedICE is true. + bool IsICE : 1; + + Stmt *Value; + APValue Evaluated; +}; + +// \brief Describes the kind of template specialization that a +// particular template specialization declaration represents. +enum TemplateSpecializationKind { + /// This template specialization was formed from a template-id but + /// has not yet been declared, defined, or instantiated. + TSK_Undeclared = 0, + /// This template specialization was implicitly instantiated from a + /// template. (C++ [temp.inst]). + TSK_ImplicitInstantiation, + /// This template specialization was declared or defined by an + /// explicit specialization (C++ [temp.expl.spec]) or partial + /// specialization (C++ [temp.class.spec]). + TSK_ExplicitSpecialization, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation declaration request + /// (C++0x [temp.explicit]). + TSK_ExplicitInstantiationDeclaration, + /// This template specialization was instantiated from a template + /// due to an explicit instantiation definition request + /// (C++ [temp.explicit]). + TSK_ExplicitInstantiationDefinition +}; + +/// VarDecl - An instance of this class is created to represent a variable +/// declaration or definition. +class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { +public: + enum StorageClass { + None, Auto, Register, Extern, Static, PrivateExtern + }; + + /// getStorageClassSpecifierString - Return the string used to + /// specify the storage class \arg SC. + /// + /// It is illegal to call this function with SC == None. + static const char *getStorageClassSpecifierString(StorageClass SC); + +protected: + /// \brief Placeholder type used in Init to denote an unparsed C++ default + /// argument. + struct UnparsedDefaultArgument; + + /// \brief Placeholder type used in Init to denote an uninstantiated C++ + /// default argument. + struct UninstantiatedDefaultArgument; + + typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *, + UnparsedDefaultArgument *, + UninstantiatedDefaultArgument *> InitType; + + /// \brief The initializer for this variable or, for a ParmVarDecl, the + /// C++ default argument. + mutable InitType Init; + +private: + // FIXME: This can be packed into the bitfields in Decl. + unsigned SClass : 3; + unsigned SClassAsWritten : 3; + bool ThreadSpecified : 1; + bool HasCXXDirectInit : 1; + + /// DeclaredInCondition - Whether this variable was declared in a + /// condition, e.g., if (int x = foo()) { ... }. + bool DeclaredInCondition : 1; + + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + bool ExceptionVar : 1; + + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization (NRVO). + bool NRVOVariable : 1; + + friend class StmtIteratorBase; +protected: + VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten) + : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), + ThreadSpecified(false), HasCXXDirectInit(false), + DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { + SClass = SC; + SClassAsWritten = SCAsWritten; + } + + typedef Redeclarable<VarDecl> redeclarable_base; + virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + +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(); + } + + static VarDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S, + StorageClass SCAsWritten); + + virtual void Destroy(ASTContext& C); + virtual ~VarDecl(); + + virtual SourceRange getSourceRange() const; + + StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClassAsWritten() const { + return (StorageClass) SClassAsWritten; + } + void setStorageClass(StorageClass SC) { SClass = SC; } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + + void setThreadSpecified(bool T) { ThreadSpecified = T; } + bool isThreadSpecified() const { + return ThreadSpecified; + } + + /// hasLocalStorage - Returns true if a variable with function scope + /// is a non-static local variable. + bool hasLocalStorage() const { + if (getStorageClass() == None) + return !isFileVarDecl(); + + // Return true for: Auto, Register. + // Return false for: Extern, Static, PrivateExtern. + + return getStorageClass() <= Register; + } + + /// isStaticLocal - Returns true if a variable with function scope is a + /// static local variable. + bool isStaticLocal() const { + return getStorageClass() == Static && !isFileVarDecl(); + } + + /// hasExternStorage - Returns true if a variable has extern or + /// __private_extern__ storage. + bool hasExternalStorage() const { + return getStorageClass() == Extern || getStorageClass() == PrivateExtern; + } + + /// hasGlobalStorage - Returns true for all variables that do not + /// have local storage. This includs all global variables as well + /// as static variables declared within a function. + bool hasGlobalStorage() const { return !hasLocalStorage(); } + + /// \brief Determines whether this variable is a variable with + /// external, C linkage. + bool isExternC() const; + + /// isBlockVarDecl - Returns true for local variable declarations. Note that + /// this includes static variables inside of functions. It also includes + /// variables inside blocks. + /// + /// void foo() { int x; static int y; extern int z; } + /// + bool isBlockVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *DC = getDeclContext()) + return DC->getLookupContext()->isFunctionOrMethod(); + return false; + } + + /// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes + /// variables declared in blocks. + bool isFunctionOrMethodVarDecl() const { + if (getKind() != Decl::Var) + return false; + if (const DeclContext *DC = getDeclContext()) + return DC->getLookupContext()->isFunctionOrMethod() && + DC->getLookupContext()->getDeclKind() != Decl::Block; + return false; + } + + /// \brief Determines whether this is a static data member. + /// + /// This will only be true in C++, and applies to, e.g., the + /// variable 'x' in: + /// \code + /// struct S { + /// static int x; + /// }; + /// \endcode + bool isStaticDataMember() const { + // If it wasn't static, it would be a FieldDecl. + return getDeclContext()->isRecord(); + } + + virtual VarDecl *getCanonicalDecl(); + const VarDecl *getCanonicalDecl() const { + return const_cast<VarDecl*>(this)->getCanonicalDecl(); + } + + enum DefinitionKind { + DeclarationOnly, ///< This declaration is only a declaration. + TentativeDefinition, ///< This declaration is a tentative definition. + Definition ///< This declaration is definitely a definition. + }; + + /// \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; + + /// \brief Get the tentative definition that acts as the real definition in + /// a TU. Returns null if there is a proper definition available. + VarDecl *getActingDefinition(); + const VarDecl *getActingDefinition() const { + return const_cast<VarDecl*>(this)->getActingDefinition(); + } + + /// \brief Determine whether this is a tentative definition of a + /// variable in C. + bool isTentativeDefinitionNow() const; + + /// \brief Get the real (not just tentative) definition for this declaration. + VarDecl *getDefinition(); + const VarDecl *getDefinition() const { + return const_cast<VarDecl*>(this)->getDefinition(); + } + + /// \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 (const DeclContext *Ctx = getDeclContext()) { + Ctx = Ctx->getLookupContext(); + if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) + return true; + } + if (isStaticDataMember()) + return true; + + return false; + } + + /// getAnyInitializer - Get the initializer for this variable, no matter which + /// declaration it is attached to. + const Expr *getAnyInitializer() const { + const VarDecl *D; + return getAnyInitializer(D); + } + + /// getAnyInitializer - Get the initializer for this variable, no matter which + /// declaration it is attached to. Also get that declaration. + const Expr *getAnyInitializer(const VarDecl *&D) const; + + bool hasInit() const { + return !Init.isNull(); + } + const Expr *getInit() const { + if (Init.isNull()) + return 0; + + const Stmt *S = Init.dyn_cast<Stmt *>(); + if (!S) { + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + S = ES->Value; + } + return (const Expr*) S; + } + Expr *getInit() { + if (Init.isNull()) + return 0; + + Stmt *S = Init.dyn_cast<Stmt *>(); + if (!S) { + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + S = ES->Value; + } + + return (Expr*) S; + } + + /// \brief Retrieve the address of the initializer expression. + Stmt **getInitAddress() { + if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) + return &ES->Value; + + // This union hack tip-toes around strict-aliasing rules. + union { + InitType *InitPtr; + Stmt **StmtPtr; + }; + + InitPtr = &Init; + return StmtPtr; + } + + void setInit(Expr *I); + + 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 Note that we now are checking whether the initializer can be + /// evaluated. + void setEvaluatingValue() const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->IsEvaluating = true; + } + + /// \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 Return the already-evaluated value of this variable's + /// initializer, or NULL if the value is not yet known. Returns pointer + /// to untyped APValue if the value could not be evaluated. + APValue *getEvaluatedValue() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + if (Eval->WasEvaluated) + return &Eval->Evaluated; + + return 0; + } + + /// \brief Determines whether it is already known whether the + /// initializer is an integral constant expression or not. + bool isInitKnownICE() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + return Eval->CheckedICE; + + return false; + } + + /// \brief Determines whether the initializer is an integral + /// constant expression. + /// + /// \pre isInitKnownICE() + bool isInitICE() const { + assert(isInitKnownICE() && + "Check whether we already know that the initializer is an ICE"); + 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 Note that we now are checking whether the initializer is an + /// integral constant expression. + void setCheckingICE() const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->CheckingICE = true; + } + + /// \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; + } + + void setCXXDirectInitializer(bool T) { 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 HasCXXDirectInit; + } + + /// isDeclaredInCondition - Whether this variable was declared as + /// part of a condition in an if/switch/while statement, e.g., + /// @code + /// if (int x = foo()) { ... } + /// @endcode + bool isDeclaredInCondition() const { + return DeclaredInCondition; + } + void setDeclaredInCondition(bool InCondition) { + DeclaredInCondition = InCondition; + } + + /// \brief Determine whether this variable is the exception variable in a + /// C++ catch statememt or an Objective-C @catch statement. + bool isExceptionVariable() const { + return ExceptionVar; + } + void setExceptionVariable(bool EV) { ExceptionVar = EV; } + + /// \brief Determine whether this local variable can be used with the named + /// return value optimization (NRVO). + /// + /// The named return value optimization (NRVO) works by marking certain + /// non-volatile local variables of class type as NRVO objects. These + /// locals can be allocated within the return slot of their containing + /// function, in which case there is no need to copy the object to the + /// return slot when returning from the function. Within the function body, + /// each return that returns the NRVO object will have this variable as its + /// NRVO candidate. + bool isNRVOVariable() const { return NRVOVariable; } + void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + + /// \brief If this variable is an instantiated static data member of a + /// class template specialization, returns the templated static data member + /// from which it was instantiated. + VarDecl *getInstantiatedFromStaticDataMember() const; + + /// \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, + SourceLocation PointOfInstantiation = SourceLocation()); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const VarDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= VarFirst && K <= VarLast; } +}; + +class ImplicitParamDecl : public VarDecl { +protected: + ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType Tw) + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} +public: + static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T); + // Implement isa/cast/dyncast/etc. + static bool classof(const ImplicitParamDecl *D) { return true; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ImplicitParam; } +}; + +/// ParmVarDecl - Represent a parameter to a function. +class ParmVarDecl : public VarDecl { + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum + /// FIXME: Also can be paced into the bitfields in Decl. + /// in, inout, etc. + unsigned objcDeclQualifier : 6; + bool HasInheritedDefaultArg : 1; + +protected: + ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten, Expr *DefArg) + : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), + objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + setDefaultArg(DefArg); + } + +public: + static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L,IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten, + Expr *DefArg); + + ObjCDeclQualifier getObjCDeclQualifier() const { + return ObjCDeclQualifier(objcDeclQualifier); + } + void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { + objcDeclQualifier = QTVal; + } + + Expr *getDefaultArg(); + 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; + void setUninstantiatedDefaultArg(Expr *arg) { + Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg); + } + Expr *getUninstantiatedDefaultArg() { + return (Expr *)Init.get<UninstantiatedDefaultArgument *>(); + } + const Expr *getUninstantiatedDefaultArg() const { + return (const Expr *)Init.get<UninstantiatedDefaultArgument *>(); + } + + /// hasDefaultArg - Determines whether this parameter has a default argument, + /// either parsed or not. + bool hasDefaultArg() const { + return getInit() || hasUnparsedDefaultArg() || + hasUninstantiatedDefaultArg(); + } + + /// hasUnparsedDefaultArg - Determines whether this parameter has a + /// default argument that has not yet been parsed. This will occur + /// during the processing of a C++ class whose member functions have + /// default arguments, e.g., + /// @code + /// class X { + /// public: + /// void f(int x = 17); // x has an unparsed default argument now + /// }; // x has a regular default argument now + /// @endcode + bool hasUnparsedDefaultArg() const { + return Init.is<UnparsedDefaultArgument*>(); + } + + bool hasUninstantiatedDefaultArg() const { + return Init.is<UninstantiatedDefaultArgument*>(); + } + + /// setUnparsedDefaultArg - Specify that this parameter has an + /// unparsed default argument. The argument will be replaced with a + /// real default argument via setDefaultArg when the class + /// definition enclosing the function declaration that owns this + /// default argument is completed. + void setUnparsedDefaultArg() { + Init = (UnparsedDefaultArgument *)0; + } + + bool hasInheritedDefaultArg() const { + return HasInheritedDefaultArg; + } + + void setHasInheritedDefaultArg(bool I = true) { + HasInheritedDefaultArg = I; + } + + QualType getOriginalType() const { + if (getTypeSourceInfo()) + return getTypeSourceInfo()->getType(); + return getType(); + } + + /// 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 + /// the DeclContext appropriately. + void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } + + // Implement isa/cast/dyncast/etc. + 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; } +}; + +/// FunctionDecl - An instance of this class is created to represent a +/// function declaration or definition. +/// +/// Since a given function can be declared several times in a program, +/// there may be several FunctionDecls that correspond to that +/// function. Only one of those FunctionDecls will be found when +/// traversing the list of declarations in the context of the +/// 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. +class FunctionDecl : public DeclaratorDecl, public DeclContext, + public Redeclarable<FunctionDecl> { +public: + enum StorageClass { + None, Extern, Static, PrivateExtern + }; + +private: + /// ParamInfo - new[]'d array of pointers to VarDecls for the formal + /// parameters of this function. This is null if a prototype or if there are + /// no formals. + ParmVarDecl **ParamInfo; + + LazyDeclStmtPtr Body; + + // FIXME: This can be packed into the bitfields in Decl. + // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum + unsigned SClass : 2; + unsigned SClassAsWritten : 2; + bool IsInline : 1; + bool IsVirtualAsWritten : 1; + bool IsPure : 1; + bool HasInheritedPrototype : 1; + bool HasWrittenPrototype : 1; + bool IsDeleted : 1; + bool IsTrivial : 1; // sunk from CXXMethodDecl + bool IsCopyAssignment : 1; // sunk from CXXMethodDecl + bool HasImplicitReturnZero : 1; + + /// \brief End part of this FunctionDecl's source range. + /// + /// We could compute the full range in getSourceRange(). However, when we're + /// dealing with a function definition deserialized from a PCH/AST file, + /// we can only compute the full range once the function body has been + /// de-serialized, so it's far better to have the (sometimes-redundant) + /// EndRangeLoc. + SourceLocation EndRangeLoc; + + /// \brief The template or declaration that this declaration + /// describes or was instantiated from, respectively. + /// + /// For non-templates, this value will be NULL. For function + /// declarations that describe a function template, this will be a + /// pointer to a FunctionTemplateDecl. For member functions + /// of class template specializations, this will be a MemberSpecializationInfo + /// pointer containing information about the specialization. + /// For function template specializations, this will be a + /// FunctionTemplateSpecializationInfo, which contains information about + /// the template being specialized and the template arguments involved in + /// that specialization. + llvm::PointerUnion4<FunctionTemplateDecl *, + MemberSpecializationInfo *, + FunctionTemplateSpecializationInfo *, + DependentFunctionTemplateSpecializationInfo *> + TemplateOrSpecialization; + +protected: + FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten, bool isInline) + : DeclaratorDecl(DK, DC, L, N, T, TInfo), + DeclContext(DK), + ParamInfo(0), Body(), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), + IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), + HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), + IsCopyAssignment(false), + HasImplicitReturnZero(false), + EndRangeLoc(L), TemplateOrSpecialization() {} + + virtual ~FunctionDecl() {} + virtual void Destroy(ASTContext& C); + + typedef Redeclarable<FunctionDecl> redeclarable_base; + virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + +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(); + } + + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName N, QualType T, + TypeSourceInfo *TInfo, + StorageClass S = None, + StorageClass SCAsWritten = None, + bool isInline = false, + bool hasWrittenPrototype = true); + + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const; + + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), EndRangeLoc); + } + void setLocEnd(SourceLocation E) { + EndRangeLoc = E; + } + + /// getBody - Retrieve the body (definition) of the function. The + /// function body might be in any of the (re-)declarations of this + /// function. The variant that accepts a FunctionDecl pointer will + /// set that function declaration to the actual declaration + /// containing the body (if there is one). + Stmt *getBody(const FunctionDecl *&Definition) const; + + virtual Stmt *getBody() const { + const FunctionDecl* Definition; + return getBody(Definition); + } + + /// isThisDeclarationADefinition - Returns whether this specific + /// declaration of the function is also a definition. This does not + /// determine whether the function has been defined (e.g., in a + /// previous definition); for that information, use getBody. + /// FIXME: Should return true if function is deleted or defaulted. However, + /// CodeGenModule.cpp uses it, and I don't know if this would break it. + bool isThisDeclarationADefinition() const { return Body; } + + void setBody(Stmt *B); + void setLazyBody(uint64_t Offset) { Body = Offset; } + + /// Whether this function is variadic. + bool isVariadic() const; + + /// Whether this function is marked as virtual explicitly. + bool isVirtualAsWritten() const { return IsVirtualAsWritten; } + void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } + + /// Whether this virtual function is pure, i.e. makes the containing class + /// abstract. + bool isPure() const { return IsPure; } + void setPure(bool P = true) { IsPure = P; } + + /// Whether this function is "trivial" in some specialized C++ senses. + /// Can only be true for default constructors, copy constructors, + /// copy assignment operators, and destructors. Not meaningful until + /// the class has been fully built by Sema. + bool isTrivial() const { return IsTrivial; } + void setTrivial(bool IT) { IsTrivial = IT; } + + bool isCopyAssignment() const { return IsCopyAssignment; } + void setCopyAssignment(bool CA) { IsCopyAssignment = CA; } + + /// Whether falling off this function implicitly returns null/zero. + /// If a more specific implicit return value is required, front-ends + /// should synthesize the appropriate return statements. + bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } + void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } + + /// \brief Whether this function has a prototype, either because one + /// was explicitly written or because it was "inherited" by merging + /// a declaration without a prototype with a declaration that has a + /// prototype. + bool hasPrototype() const { + return HasWrittenPrototype || HasInheritedPrototype; + } + + bool hasWrittenPrototype() const { return HasWrittenPrototype; } + void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; } + + /// \brief Whether this function inherited its prototype from a + /// previous declaration. + bool hasInheritedPrototype() const { return HasInheritedPrototype; } + void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } + + /// \brief Whether this function has been deleted. + /// + /// A function that is "deleted" (via the C++0x "= delete" syntax) + /// acts like a normal function, except that it cannot actually be + /// called or have its address taken. Deleted functions are + /// typically used in C++ overload resolution to attract arguments + /// whose type or lvalue/rvalue-ness would permit the use of a + /// different overload that would behave incorrectly. For example, + /// one might use deleted functions to ban implicit conversion from + /// a floating-point number to an Integer type: + /// + /// @code + /// struct Integer { + /// Integer(long); // construct from a long + /// Integer(double) = delete; // no construction from float or double + /// Integer(long double) = delete; // no construction from long double + /// }; + /// @endcode + bool isDeleted() const { return IsDeleted; } + void setDeleted(bool D = true) { IsDeleted = D; } + + /// \brief Determines whether this is a function "main", which is + /// the entry point into an executable program. + bool isMain() const; + + /// \brief Determines whether this function is a function with + /// external, C linkage. + bool isExternC() const; + + /// \brief Determines whether this is a global function. + bool isGlobal() const; + + void setPreviousDeclaration(FunctionDecl * PrevDecl); + + virtual const FunctionDecl *getCanonicalDecl() const; + virtual FunctionDecl *getCanonicalDecl(); + + unsigned getBuiltinID() const; + + // Iterator access to formal parameters. + unsigned param_size() const { return getNumParams(); } + typedef ParmVarDecl **param_iterator; + typedef ParmVarDecl * const *param_const_iterator; + + param_iterator param_begin() { return ParamInfo; } + param_iterator param_end() { return ParamInfo+param_size(); } + + param_const_iterator param_begin() const { return ParamInfo; } + param_const_iterator param_end() const { return ParamInfo+param_size(); } + + /// getNumParams - Return the number of parameters this function must have + /// based on its FunctionType. This is the length of the ParamInfo array + /// after it has been created. + unsigned getNumParams() const; + + const ParmVarDecl *getParamDecl(unsigned i) const { + assert(i < getNumParams() && "Illegal param #"); + return ParamInfo[i]; + } + ParmVarDecl *getParamDecl(unsigned i) { + assert(i < getNumParams() && "Illegal param #"); + return ParamInfo[i]; + } + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + + /// 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 + /// arguments (in C++). + unsigned getMinRequiredArguments() const; + + QualType getResultType() const { + return getType()->getAs<FunctionType>()->getResultType(); + } + StorageClass getStorageClass() const { return StorageClass(SClass); } + void setStorageClass(StorageClass SC) { SClass = SC; } + + StorageClass getStorageClassAsWritten() const { + return StorageClass(SClassAsWritten); + } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + + /// \brief Determine whether the "inline" keyword was specified for this + /// function. + bool isInlineSpecified() const { return IsInline; } + + /// Set whether the "inline" keyword was specified for this function. + void setInlineSpecified(bool I) { IsInline = I; } + + /// \brief Determine whether this function should be inlined, because it is + /// either marked "inline" or is a member function of a C++ class that + /// was defined in the class body. + bool isInlined() const; + + bool isInlineDefinitionExternallyVisible() const; + + /// isOverloadedOperator - Whether this function declaration + /// represents an C++ overloaded operator, e.g., "operator+". + bool isOverloadedOperator() const { + return getOverloadedOperator() != OO_None; + } + + OverloadedOperatorKind getOverloadedOperator() const; + + const IdentifierInfo *getLiteralIdentifier() const; + + /// \brief If this function is an instantiation of a member function + /// of a class template specialization, retrieves the function from + /// which it was instantiated. + /// + /// This routine will return non-NULL for (non-templated) member + /// functions of class templates and for instantiations of function + /// templates. For example, given: + /// + /// \code + /// template<typename T> + /// struct X { + /// void f(T); + /// }; + /// \endcode + /// + /// The declaration for X<int>::f is a (non-templated) FunctionDecl + /// whose parent is the class template specialization X<int>. For + /// this declaration, getInstantiatedFromFunction() will return + /// the FunctionDecl X<T>::A. When a complete definition of + /// X<int>::A is required, it will be instantiated from the + /// declaration returned by getInstantiatedFromMemberFunction(). + FunctionDecl *getInstantiatedFromMemberFunction() const; + + /// \brief If this function is an instantiation of a member function of a + /// 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, + TemplateSpecializationKind TSK); + + /// \brief Retrieves the function template that is described by this + /// function declaration. + /// + /// Every function template is represented as a FunctionTemplateDecl + /// and a FunctionDecl (or something derived from FunctionDecl). The + /// former contains template properties (such as the template + /// parameter lists) while the latter contains the actual + /// description of the template's + /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the + /// FunctionDecl that describes the function template, + /// getDescribedFunctionTemplate() retrieves the + /// FunctionTemplateDecl from a FunctionDecl. + FunctionTemplateDecl *getDescribedFunctionTemplate() const { + return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>(); + } + + void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + TemplateOrSpecialization = Template; + } + + /// \brief Determine whether this function is a function template + /// specialization. + bool isFunctionTemplateSpecialization() const { + return getPrimaryTemplate() != 0; + } + + /// \brief If this function is actually a function template specialization, + /// retrieve information about this function template specialization. + /// Otherwise, returns NULL. + FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { + return TemplateOrSpecialization. + dyn_cast<FunctionTemplateSpecializationInfo*>(); + } + + /// \brief Determines whether this function is a function template + /// specialization or a member of a class template specialization that can + /// be implicitly instantiated. + bool isImplicitlyInstantiable() const; + + /// \brief Retrieve the function declaration from which this function could + /// be instantiated, if it is an instantiation (rather than a non-template + /// or a specialization, for example). + FunctionDecl *getTemplateInstantiationPattern() const; + + /// \brief Retrieve the primary template that this function template + /// specialization either specializes or was instantiated from. + /// + /// If this function declaration is not a function template specialization, + /// returns NULL. + FunctionTemplateDecl *getPrimaryTemplate() const; + + /// \brief Retrieve the template arguments used to produce this function + /// template specialization from the primary template. + /// + /// If this function declaration is not a function template specialization, + /// returns NULL. + const TemplateArgumentList *getTemplateSpecializationArgs() const; + + /// \brief Retrieve the template argument list as written in the sources, + /// if any. + /// + /// If this function declaration is not a function template specialization + /// or if it had no explicit template argument list, returns NULL. + /// Note that it an explicit template argument list may be written empty, + /// e.g., template<> void foo<>(char* s); + const TemplateArgumentListInfo* + getTemplateSpecializationArgsAsWritten() const; + + /// \brief Specify that this function declaration is actually a function + /// template specialization. + /// + /// \param Context the AST context in which this function resides. + /// + /// \param Template the function template that this function template + /// specialization specializes. + /// + /// \param TemplateArgs the template arguments that produced this + /// function template specialization from the template. + /// + /// \param InsertPos If non-NULL, the position in the function template + /// specialization set where the function template specialization data will + /// be inserted. + /// + /// \param TSK the kind of template specialization this is. + void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, + const TemplateArgumentListInfo *TemplateArgsAsWritten = 0); + + /// \brief Specifies that this function declaration is actually a + /// dependent function template specialization. + void setDependentTemplateSpecialization(ASTContext &Context, + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + DependentFunctionTemplateSpecializationInfo * + getDependentSpecializationInfo() const { + return TemplateOrSpecialization. + dyn_cast<DependentFunctionTemplateSpecializationInfo*>(); + } + + /// \brief Determine what kind of template instantiation this function + /// represents. + TemplateSpecializationKind getTemplateSpecializationKind() const; + + /// \brief Determine what kind of template instantiation this function + /// represents. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); + + /// \brief Retrieve the (first) point of instantiation of a function template + /// specialization or a member of a class template specialization. + /// + /// \returns the first point of instantiation, if this function was + /// instantiated from a template; otherwie, returns an invalid source + /// location. + SourceLocation getPointOfInstantiation() const; + + /// \brief Determine whether this is or was instantiated from an out-of-line + /// definition of a member function. + virtual bool isOutOfLine() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FunctionDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= FunctionFirst && K <= FunctionLast; + } + static DeclContext *castToDeclContext(const FunctionDecl *D) { + return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D)); + } + static FunctionDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); + } +}; + + +/// FieldDecl - An instance of this class is created by Sema::ActOnField to +/// represent a member of a struct/union/class. +class FieldDecl : public DeclaratorDecl { + // FIXME: This can be packed into the bitfields in Decl. + bool Mutable : 1; + Expr *BitWidth; +protected: + FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + Expr *BW, bool Mutable) + : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) { + } + +public: + static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, Expr *BW, bool Mutable); + + /// isMutable - Determines whether this field is mutable (C++ only). + bool isMutable() const { return Mutable; } + + /// \brief Set whether this field is mutable (C++ only). + void setMutable(bool M) { Mutable = M; } + + /// isBitfield - Determines whether this field is a bitfield. + bool isBitField() const { return BitWidth != NULL; } + + /// @brief Determines whether this is an unnamed bitfield. + bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); } + + /// isAnonymousStructOrUnion - Determines whether this field is a + /// representative for an anonymous struct or union. Such fields are + /// unnamed and are implicitly generated by the implementation to + /// store the data for the anonymous union or struct. + bool isAnonymousStructOrUnion() const; + + Expr *getBitWidth() const { return BitWidth; } + void setBitWidth(Expr *BW) { BitWidth = BW; } + + /// getParent - Returns the parent of this field declaration, which + /// is the struct in which this method is defined. + const RecordDecl *getParent() const { + return cast<RecordDecl>(getDeclContext()); + } + + RecordDecl *getParent() { + return cast<RecordDecl>(getDeclContext()); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FieldDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= FieldFirst && K <= FieldLast; } +}; + +/// EnumConstantDecl - An instance of this object exists for each enum constant +/// that is defined. For example, in "enum X {a,b}", each of a/b are +/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a +/// TagType for the X EnumDecl. +class EnumConstantDecl : public ValueDecl { + Stmt *Init; // an integer constant expression + llvm::APSInt Val; // The value. +protected: + EnumConstantDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, Expr *E, + const llvm::APSInt &V) + : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} + + virtual ~EnumConstantDecl() {} +public: + + static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, + SourceLocation L, IdentifierInfo *Id, + QualType T, Expr *E, + const llvm::APSInt &V); + + virtual void Destroy(ASTContext& C); + + const Expr *getInitExpr() const { return (const Expr*) Init; } + Expr *getInitExpr() { return (Expr*) Init; } + const llvm::APSInt &getInitVal() const { return Val; } + + void setInitExpr(Expr *E) { Init = (Stmt*) E; } + void setInitVal(const llvm::APSInt &V) { Val = V; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const EnumConstantDecl *D) { return true; } + static bool classofKind(Kind K) { return K == EnumConstant; } + + friend class StmtIteratorBase; +}; + + +/// TypeDecl - Represents a declaration of a type. +/// +class TypeDecl : public NamedDecl { + /// TypeForDecl - This indicates the Type object that represents + /// this TypeDecl. It is a cache maintained by + /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and + /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. + mutable Type *TypeForDecl; + friend class ASTContext; + friend class DeclContext; + friend class TagDecl; + friend class TemplateTypeParmDecl; + friend class TagType; + +protected: + TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} + +public: + // Low-level accessor + Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(Type *TD) { TypeForDecl = TD; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= TypeFirst && K <= TypeLast; } +}; + + +class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { + /// UnderlyingType - This is the type the typedef is set to. + TypeSourceInfo *TInfo; + + TypedefDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} + + virtual ~TypedefDecl(); + +protected: + typedef Redeclarable<TypedefDecl> redeclarable_base; + virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + +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(); + } + + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + TypeSourceInfo *TInfo); + + TypeSourceInfo *getTypeSourceInfo() const { + return TInfo; + } + + /// Retrieves the canonical declaration of this typedef. + TypedefDecl *getCanonicalDecl() { + return getFirstDeclaration(); + } + const TypedefDecl *getCanonicalDecl() const { + return getFirstDeclaration(); + } + + QualType getUnderlyingType() const { + return TInfo->getType(); + } + void setTypeSourceInfo(TypeSourceInfo *newType) { + TInfo = newType; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypedefDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Typedef; } +}; + +class TypedefDecl; + +/// TagDecl - Represents the declaration of a struct/union/class/enum. +class TagDecl + : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { +public: + // This is really ugly. + typedef TagTypeKind TagKind; + +private: + // FIXME: This can be packed into the bitfields in Decl. + /// TagDeclKind - The TagKind enum. + unsigned TagDeclKind : 2; + + /// IsDefinition - True if this is a definition ("struct foo {};"), false if + /// it is a declaration ("struct foo;"). + bool IsDefinition : 1; + + /// 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; + +protected: + // These are used by (and only defined for) EnumDecl. + unsigned NumPositiveBits : 8; + unsigned NumNegativeBits : 8; + +private: + SourceLocation TagKeywordLoc; + SourceLocation RBraceLoc; + + // A struct representing syntactic qualifier info, + // to be used for the (uncommon) case of out-of-line declarations. + struct ExtInfo { + NestedNameSpecifier *NNS; + SourceRange NNSRange; + }; + + /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name + /// is qualified, it points to the qualifier info (nns and range); + /// otherwise, if the tag declaration is anonymous and it is part of + /// a typedef, it points to the TypedefDecl (used for mangling); + /// otherwise, it is a null (TypedefDecl) pointer. + llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier; + + bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); } + ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); } + const ExtInfo *getExtInfo() const { + return TypedefDeclOrQualifier.get<ExtInfo*>(); + } + +protected: + TagDecl(Kind DK, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) + : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), + TypedefDeclOrQualifier((TypedefDecl*) 0) { + assert((DK != Enum || TK == TTK_Enum) && + "EnumDecl not matched with TTK_Enum"); + TagDeclKind = TK; + IsDefinition = false; + IsEmbeddedInDeclarator = false; + setPreviousDeclaration(PrevDecl); + } + + typedef Redeclarable<TagDecl> redeclarable_base; + virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + +public: + void Destroy(ASTContext &C); + + 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(); + } + + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } + void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } + + virtual SourceRange getSourceRange() const; + + virtual TagDecl* getCanonicalDecl(); + const TagDecl* getCanonicalDecl() const { + return const_cast<TagDecl*>(this)->getCanonicalDecl(); + } + + /// isDefinition - Return true if this decl has its body specified. + bool isDefinition() const { + return IsDefinition; + } + + bool isEmbeddedInDeclarator() const { + return IsEmbeddedInDeclarator; + } + void setEmbeddedInDeclarator(bool isInDeclarator) { + IsEmbeddedInDeclarator = isInDeclarator; + } + + /// \brief Whether this declaration declares a type that is + /// dependent, i.e., a type that somehow depends on template + /// parameters. + bool isDependentType() const { return isDependentContext(); } + + /// @brief Starts the definition of this tag declaration. + /// + /// This method should be invoked at the beginning of the definition + /// of this tag declaration. It will set the tag type into a state + /// where it is in the process of being defined. + void startDefinition(); + + /// @brief Completes the definition of this tag declaration. + void completeDefinition(); + + /// getDefinition - Returns the TagDecl that actually defines this + /// struct/union/class/enum. When determining whether or not a + /// struct/union/class/enum is completely defined, one should use this method + /// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a + /// specific TagDecl is defining declaration, not whether or not the + /// struct/union/class/enum type is defined. This method returns NULL if + /// there is no TagDecl that defines the struct/union/class/enum. + TagDecl* getDefinition() const; + + void setDefinition(bool V) { IsDefinition = V; } + + const char *getKindName() const { + return TypeWithKeyword::getTagTypeKindName(getTagKind()); + } + + TagKind getTagKind() const { + return TagKind(TagDeclKind); + } + + void setTagKind(TagKind TK) { TagDeclKind = TK; } + + bool isStruct() const { return getTagKind() == TTK_Struct; } + bool isClass() const { return getTagKind() == TTK_Class; } + bool isUnion() const { return getTagKind() == TTK_Union; } + bool isEnum() const { return getTagKind() == TTK_Enum; } + + TypedefDecl *getTypedefForAnonDecl() const { + return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); + } + + void setTypedefForAnonDecl(TypedefDecl *TDD); + + NestedNameSpecifier *getQualifier() const { + return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; + } + SourceRange getQualifierRange() const { + return hasExtInfo() + ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange + : SourceRange(); + } + void setQualifierInfo(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TagDecl *D) { return true; } + static bool classofKind(Kind K) { return K >= TagFirst && K <= TagLast; } + + static DeclContext *castToDeclContext(const TagDecl *D) { + return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); + } + static TagDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// EnumDecl - Represents an enum. As an extension, we allow forward-declared +/// enums. +class EnumDecl : public TagDecl { + /// 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. + QualType IntegerType; + + /// PromotionType - The integer type that values of this type should + /// promote to. In C, enumerators are generally of an integer type + /// directly, but gcc-style large enumerators (and all enumerators + /// 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 + }; + + EnumDecl(DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) + : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { + IntegerType = QualType(); + } +public: + EnumDecl *getCanonicalDecl() { + return cast<EnumDecl>(TagDecl::getCanonicalDecl()); + } + const EnumDecl *getCanonicalDecl() const { + return cast<EnumDecl>(TagDecl::getCanonicalDecl()); + } + + static EnumDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + SourceLocation TKL, EnumDecl *PrevDecl); + + virtual void Destroy(ASTContext& C); + + /// completeDefinition - When created, the EnumDecl corresponds to a + /// forward-declared enum. This method is used to mark the + /// declaration as being defined; it's enumerators have already been + /// added (via DeclContext::addDecl). NewType is the new underlying + /// type of the enumeration type. + void completeDefinition(QualType NewType, + QualType PromotionType, + unsigned NumPositiveBits, + unsigned NumNegativeBits); + + // enumerator_iterator - Iterates through the enumerators of this + // enumeration. + typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; + + enumerator_iterator enumerator_begin() const { + return enumerator_iterator(this->decls_begin()); + } + + enumerator_iterator enumerator_end() const { + return enumerator_iterator(this->decls_end()); + } + + /// getPromotionType - Return the integer type that enumerators + /// should promote to. + QualType getPromotionType() const { return PromotionType; } + + /// \brief Set the promotion type. + void setPromotionType(QualType T) { PromotionType = T; } + + /// getIntegerType - Return the integer type this enum decl corresponds to. + /// This returns a null qualtype for an enum forward definition. + QualType getIntegerType() const { return IntegerType; } + + /// \brief Set the underlying integer type. + void setIntegerType(QualType T) { IntegerType = T; } + + /// \brief Returns the width in bits requred to store all the + /// non-negative enumerators of this enum. + unsigned getNumPositiveBits() const { + return NumPositiveBits; + } + void setNumPositiveBits(unsigned Num) { + NumPositiveBits = Num; + assert(NumPositiveBits == Num && "can't store this bitcount"); + } + + /// \brief Returns the width in bits requred 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 + /// -10 1110110 5 + /// -101 1001011 8 + unsigned getNumNegativeBits() const { + return NumNegativeBits; + } + void setNumNegativeBits(unsigned Num) { + NumNegativeBits = Num; + } + + /// \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; + } + + void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const EnumDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Enum; } +}; + + +/// RecordDecl - Represents a struct/union/class. For example: +/// struct X; // Forward declaration, no "body". +/// union Y { int A, B; }; // Has body with members A and B (FieldDecls). +/// This decl will be marked invalid if *any* members are invalid. +/// +class RecordDecl : public TagDecl { + // FIXME: This can be packed into the bitfields in Decl. + /// HasFlexibleArrayMember - This is true if this struct ends with a flexible + /// array member (e.g. int X[]) or if this union contains a struct that does. + /// If so, this cannot be contained in arrays or other structs as a member. + bool HasFlexibleArrayMember : 1; + + /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct + /// or union. + bool AnonymousStructOrUnion : 1; + + /// HasObjectMember - This is true if this struct has at least one member + /// containing an object. + bool HasObjectMember : 1; + +protected: + RecordDecl(Kind DK, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + RecordDecl *PrevDecl, SourceLocation TKL); + virtual ~RecordDecl(); + +public: + static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + SourceLocation TKL = SourceLocation(), + RecordDecl* PrevDecl = 0); + + virtual void Destroy(ASTContext& C); + + bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } + void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } + + /// isAnonymousStructOrUnion - Whether this is an anonymous struct + /// or union. To be an anonymous struct or union, it must have been + /// declared without a name and there must be no objects of this + /// type declared, e.g., + /// @code + /// union { int i; float f; }; + /// @endcode + /// is an anonymous union but neither of the following are: + /// @code + /// union X { int i; float f; }; + /// union { int i; float f; } obj; + /// @endcode + bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; } + void setAnonymousStructOrUnion(bool Anon) { + AnonymousStructOrUnion = Anon; + } + + ValueDecl *getAnonymousStructOrUnionObject(); + const ValueDecl *getAnonymousStructOrUnionObject() const { + return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject(); + } + + bool hasObjectMember() const { return HasObjectMember; } + void setHasObjectMember (bool val) { HasObjectMember = val; } + + /// \brief Determines whether this declaration represents the + /// injected class name. + /// + /// The injected class name in C++ is the name of the class that + /// appears inside the class itself. For example: + /// + /// \code + /// struct C { + /// // C is implicitly declared here as a synonym for the class name. + /// }; + /// + /// C::C c; // same as "C c;" + /// \endcode + bool isInjectedClassName() const; + + /// getDefinition - Returns the RecordDecl that actually defines this + /// struct/union/class. When determining whether or not a struct/union/class + /// is completely defined, one should use this method as opposed to + /// 'isDefinition'. 'isDefinition' indicates whether or not a specific + /// RecordDecl is defining declaration, not whether or not the record + /// type is defined. This method returns NULL if there is no RecordDecl + /// that defines the struct/union/tag. + RecordDecl* getDefinition() const { + return cast_or_null<RecordDecl>(TagDecl::getDefinition()); + } + + // Iterator access to field members. The field iterator only visits + // the non-static data members of this class, ignoring any static + // data members, functions, constructors, destructors, etc. + typedef specific_decl_iterator<FieldDecl> field_iterator; + + field_iterator field_begin() const { + return field_iterator(decls_begin()); + } + field_iterator field_end() const { + return field_iterator(decls_end()); + } + + // field_empty - Whether there are any fields (non-static data + // members) in this record. + bool field_empty() const { + return field_begin() == field_end(); + } + + /// completeDefinition - Notes that the definition of this type is + /// now complete. + void completeDefinition(); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const RecordDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= RecordFirst && K <= RecordLast; + } +}; + +class FileScopeAsmDecl : public Decl { + StringLiteral *AsmString; + FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) + : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} +public: + static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, StringLiteral *Str); + + const StringLiteral *getAsmString() const { return AsmString; } + StringLiteral *getAsmString() { return AsmString; } + void setAsmString(StringLiteral *Asm) { AsmString = Asm; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FileScopeAsmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == FileScopeAsm; } +}; + +/// BlockDecl - This represents a block literal declaration, which is like an +/// unnamed FunctionDecl. For example: +/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } +/// +class BlockDecl : public Decl, public DeclContext { + // FIXME: This can be packed into the bitfields in Decl. + bool IsVariadic : 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. + ParmVarDecl **ParamInfo; + unsigned NumParams; + + Stmt *Body; + +protected: + BlockDecl(DeclContext *DC, SourceLocation CaretLoc) + : Decl(Block, DC, CaretLoc), DeclContext(Block), + IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} + + virtual ~BlockDecl(); + virtual void Destroy(ASTContext& C); + +public: + static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); + + SourceLocation getCaretLocation() const { return getLocation(); } + + bool isVariadic() const { return IsVariadic; } + void setIsVariadic(bool value) { IsVariadic = value; } + + CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } + Stmt *getBody() const { return (Stmt*) Body; } + void setBody(CompoundStmt *B) { Body = (Stmt*) B; } + + // Iterator access to formal parameters. + unsigned param_size() const { return getNumParams(); } + typedef ParmVarDecl **param_iterator; + typedef ParmVarDecl * const *param_const_iterator; + + bool param_empty() const { return NumParams == 0; } + param_iterator param_begin() { return ParamInfo; } + param_iterator param_end() { return ParamInfo+param_size(); } + + param_const_iterator param_begin() const { return ParamInfo; } + param_const_iterator param_end() const { return ParamInfo+param_size(); } + + unsigned getNumParams() const; + const ParmVarDecl *getParamDecl(unsigned i) const { + assert(i < getNumParams() && "Illegal param #"); + return ParamInfo[i]; + } + ParmVarDecl *getParamDecl(unsigned i) { + assert(i < getNumParams() && "Illegal param #"); + return ParamInfo[i]; + } + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const BlockDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Block; } + static DeclContext *castToDeclContext(const BlockDecl *D) { + return static_cast<DeclContext *>(const_cast<BlockDecl*>(D)); + } + static BlockDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// Insertion operator for diagnostics. This allows sending NamedDecl's +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + NamedDecl* ND) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl); + return DB; +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h b/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h new file mode 100644 index 0000000..7ecd8f8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h @@ -0,0 +1,72 @@ +//===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 DeclAccessPair class, which provides an +// efficient representation of a pair of a NamedDecl* and an +// AccessSpecifier. Generally the access specifier gives the +// natural access of a declaration when named in a class, as +// defined in C++ [class.access.base]p1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H +#define LLVM_CLANG_AST_DECLACCESSPAIR_H + +#include "clang/Basic/Specifiers.h" + +namespace clang { + +class NamedDecl; + +/// A POD class for pairing a NamedDecl* with an access specifier. +/// Can be put into unions. +class DeclAccessPair { + NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial + + enum { Mask = 0x3 }; + +public: + static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { + DeclAccessPair p; + p.set(D, AS); + return p; + } + + NamedDecl *getDecl() const { + return (NamedDecl*) (~Mask & (uintptr_t) Ptr); + } + AccessSpecifier getAccess() const { + return AccessSpecifier(Mask & (uintptr_t) Ptr); + } + + void setDecl(NamedDecl *D) { + set(D, getAccess()); + } + void setAccess(AccessSpecifier AS) { + set(getDecl(), AS); + } + void set(NamedDecl *D, AccessSpecifier AS) { + Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | + reinterpret_cast<uintptr_t>(D)); + } + + operator NamedDecl*() const { return getDecl(); } + NamedDecl *operator->() const { return getDecl(); } +}; +} + +// Take a moment to tell SmallVector that DeclAccessPair is POD. +namespace llvm { +template<typename> struct isPodLike; +template<> struct isPodLike<clang::DeclAccessPair> { + static const bool value = true; +}; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h new file mode 100644 index 0000000..c15aeef --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h @@ -0,0 +1,1211 @@ +//===-- DeclBase.h - Base Classes for representing declarations -*- 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 Decl and DeclContext interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLBASE_H +#define LLVM_CLANG_AST_DECLBASE_H + +#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" + +namespace clang { +class DeclContext; +class TranslationUnitDecl; +class NamespaceDecl; +class UsingDirectiveDecl; +class NamedDecl; +class FunctionDecl; +class CXXRecordDecl; +class EnumDecl; +class ObjCMethodDecl; +class ObjCContainerDecl; +class ObjCInterfaceDecl; +class ObjCCategoryDecl; +class ObjCProtocolDecl; +class ObjCImplementationDecl; +class ObjCCategoryImplDecl; +class ObjCImplDecl; +class LinkageSpecDecl; +class BlockDecl; +class DeclarationName; +class CompoundStmt; +class StoredDeclsMap; +class DependentDiagnostic; +} + +namespace llvm { +// DeclContext* is only 4-byte aligned on 32-bit systems. +template<> + class PointerLikeTypeTraits<clang::DeclContext*> { + typedef clang::DeclContext* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; +} + +namespace clang { + +/// Decl - This represents one declaration (or definition), e.g. a variable, +/// typedef, function, struct, etc. +/// +class Decl { +public: + /// \brief Lists the kind of concrete classes of Decl. + enum Kind { +#define DECL(Derived, Base) Derived, +#define DECL_RANGE(CommonBase, Start, End) \ + CommonBase##First = Start, CommonBase##Last = End, +#define LAST_DECL_RANGE(CommonBase, Start, End) \ + CommonBase##First = Start, CommonBase##Last = End +#include "clang/AST/DeclNodes.def" + }; + + /// \brief A placeholder type used to construct an empty shell of a + /// decl-derived type that will be filled in later (e.g., by some + /// deserialization method). + struct EmptyShell { }; + + /// IdentifierNamespace - The different namespaces in which + /// declarations may appear. According to C99 6.2.3, there are + /// four namespaces, labels, tags, members and ordinary + /// 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. + /// + /// Decl currently provides 16 bits of IDNS bits. + enum IdentifierNamespace { + /// Labels, declared with 'x:' and referenced with 'goto x'. + IDNS_Label = 0x0001, + + /// Tags, declared with 'struct foo;' and referenced with + /// 'struct foo'. All tags are also types. This is what + /// elaborated-type-specifiers look for in C. + IDNS_Tag = 0x0002, + + /// Types, declared with 'struct foo', typedefs, etc. + /// This is what elaborated-type-specifiers look for in C++, + /// but note that it's ill-formed to find a non-tag. + IDNS_Type = 0x0004, + + /// Members, declared with object declarations within tag + /// definitions. In C, these can only be found by "qualified" + /// lookup in member expressions. In C++, they're found by + /// normal lookup. + IDNS_Member = 0x0008, + + /// Namespaces, declared with 'namespace foo {}'. + /// Lookup for nested-name-specifiers find these. + IDNS_Namespace = 0x0010, + + /// Ordinary names. In C, everything that's not a label, tag, + /// or member ends up here. + IDNS_Ordinary = 0x0020, + + /// Objective C @protocol. + IDNS_ObjCProtocol = 0x0040, + + /// This declaration is a friend function. A friend function + /// declaration is always in this namespace but may also be in + /// IDNS_Ordinary if it was previously declared. + IDNS_OrdinaryFriend = 0x0080, + + /// This declaration is a friend class. A friend class + /// declaration is always in this namespace but may also be in + /// IDNS_Tag|IDNS_Type if it was previously declared. + IDNS_TagFriend = 0x0100, + + /// This declaration is a using declaration. A using declaration + /// *introduces* a number of other declarations into the current + /// scope, and those declarations use the IDNS of their targets, + /// but the actual using declarations go in this namespace. + IDNS_Using = 0x0200, + + /// This declaration is a C++ operator declared in a non-class + /// context. All such operators are also in IDNS_Ordinary. + /// C++ lexical operator lookup looks for these. + IDNS_NonMemberOperator = 0x0400 + }; + + /// ObjCDeclQualifier - Qualifier used on types in method declarations + /// for remote messaging. They are meant for the arguments though and + /// applied to the Decls (ObjCMethodDecl and ParmVarDecl). + enum ObjCDeclQualifier { + OBJC_TQ_None = 0x0, + OBJC_TQ_In = 0x1, + OBJC_TQ_Inout = 0x2, + OBJC_TQ_Out = 0x4, + OBJC_TQ_Bycopy = 0x8, + OBJC_TQ_Byref = 0x10, + OBJC_TQ_Oneway = 0x20 + }; + +private: + /// NextDeclInContext - 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; + + friend class DeclContext; + + struct MultipleDC { + DeclContext *SemanticDC; + DeclContext *LexicalDC; + }; + + + /// DeclCtx - Holds either a DeclContext* or a MultipleDC*. + /// For declarations that don't contain C++ scope specifiers, it contains + /// the DeclContext where the Decl was declared. + /// For declarations with C++ scope specifiers, it contains a MultipleDC* + /// with the context where it semantically belongs (SemanticDC) and the + /// context where it was lexically declared (LexicalDC). + /// e.g.: + /// + /// namespace A { + /// void f(); // SemanticDC == LexicalDC == 'namespace A' + /// } + /// void A::f(); // SemanticDC == namespace 'A' + /// // LexicalDC == global namespace + llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx; + + inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } + inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } + inline MultipleDC *getMultipleDC() const { + return DeclCtx.get<MultipleDC*>(); + } + inline DeclContext *getSemanticDC() const { + return DeclCtx.get<DeclContext*>(); + } + + /// Loc - The location that this decl. + SourceLocation Loc; + + /// DeclKind - This indicates which class this is. + Kind DeclKind : 8; + + /// InvalidDecl - This indicates a semantic error occurred. + unsigned int InvalidDecl : 1; + + /// HasAttrs - This indicates whether the decl has attributes or not. + unsigned int HasAttrs : 1; + + /// Implicit - Whether this declaration was implicitly generated by + /// the implementation rather than explicitly written by the user. + bool Implicit : 1; + + /// \brief Whether this declaration was "used", meaning that a definition is + /// required. + bool Used : 1; + +protected: + /// Access - Used by C++ decls for the access specifier. + // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum + unsigned Access : 2; + friend class CXXClassMemberWrapper; + + // PCHLevel - the "level" of precompiled header/AST file from which this + // declaration was built. + unsigned PCHLevel : 2; + + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. + unsigned IdentifierNamespace : 16; + +private: +#ifndef NDEBUG + void CheckAccessDeclContext() const; +#else + void CheckAccessDeclContext() const { } +#endif + +protected: + + Decl(Kind DK, DeclContext *DC, SourceLocation L) + : NextDeclInContext(0), DeclCtx(DC), + Loc(L), DeclKind(DK), InvalidDecl(0), + HasAttrs(false), Implicit(false), Used(false), + Access(AS_none), PCHLevel(0), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { + if (Decl::CollectingStats()) addDeclKind(DK); + } + + virtual ~Decl(); + +public: + + /// \brief Source range that this declaration covers. + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), getLocation()); + } + SourceLocation getLocStart() const { return getSourceRange().getBegin(); } + SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + Kind getKind() const { return DeclKind; } + const char *getDeclKindName() const; + + Decl *getNextDeclInContext() { return NextDeclInContext; } + const Decl *getNextDeclInContext() const { return NextDeclInContext; } + + DeclContext *getDeclContext() { + if (isInSemaDC()) + return getSemanticDC(); + return getMultipleDC()->SemanticDC; + } + const DeclContext *getDeclContext() const { + return const_cast<Decl*>(this)->getDeclContext(); + } + + TranslationUnitDecl *getTranslationUnitDecl(); + const TranslationUnitDecl *getTranslationUnitDecl() const { + return const_cast<Decl*>(this)->getTranslationUnitDecl(); + } + + bool isInAnonymousNamespace() const; + + ASTContext &getASTContext() const; + + void setAccess(AccessSpecifier AS) { + Access = AS; + CheckAccessDeclContext(); + } + + AccessSpecifier getAccess() const { + CheckAccessDeclContext(); + return AccessSpecifier(Access); + } + + bool hasAttrs() const { return HasAttrs; } + void addAttr(Attr *attr); + const Attr *getAttrs() const { + if (!HasAttrs) return 0; // common case, no attributes. + return getAttrsImpl(); // Uncommon case, out of line hash lookup. + } + void swapAttrs(Decl *D); + void invalidateAttrs(); + + template<typename T> const T *getAttr() const { + for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) + if (const T *V = dyn_cast<T>(attr)) + return V; + return 0; + } + + template<typename T> bool hasAttr() const { + return getAttr<T>() != 0; + } + + /// setInvalidDecl - Indicates the Decl had a semantic error. This + /// allows for graceful error recovery. + void setInvalidDecl(bool Invalid = true); + bool isInvalidDecl() const { return (bool) InvalidDecl; } + + /// isImplicit - Indicates whether the declaration was implicitly + /// generated by the implementation. If false, this declaration + /// was written explicitly in the source code. + bool isImplicit() const { return Implicit; } + void setImplicit(bool I = true) { Implicit = I; } + + /// \brief Whether this declaration was used, meaning that a definition + /// is required. + bool isUsed() const; + + void setUsed(bool U = true) { Used = U; } + + /// \brief Retrieve the level of precompiled header from which this + /// declaration was generated. + /// + /// The PCH level of a declaration describes where the declaration originated + /// from. A PCH level of 0 indicates that the declaration was not from a + /// precompiled header. A PCH level of 1 indicates that the declaration was + /// from a top-level precompiled header; 2 indicates that the declaration + /// comes from a precompiled header on which the top-level precompiled header + /// depends, and so on. + unsigned getPCHLevel() const { return PCHLevel; } + + /// \brief The maximum PCH level that any declaration may have. + static const unsigned MaxPCHLevel = 3; + + /// \brief Set the PCH level of this declaration. + void setPCHLevel(unsigned Level) { + assert(Level < MaxPCHLevel && "PCH level exceeds the maximum"); + PCHLevel = Level; + } + + unsigned getIdentifierNamespace() const { + return IdentifierNamespace; + } + bool isInIdentifierNamespace(unsigned NS) const { + return getIdentifierNamespace() & NS; + } + static unsigned getIdentifierNamespaceForKind(Kind DK); + + bool hasTagIdentifierNamespace() const { + return isTagIdentifierNamespace(getIdentifierNamespace()); + } + static bool isTagIdentifierNamespace(unsigned NS) { + // TagDecls have Tag and Type set and may also have TagFriend. + return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type); + } + + /// getLexicalDeclContext - The declaration context where this Decl was + /// lexically declared (LexicalDC). May be different from + /// getDeclContext() (SemanticDC). + /// e.g.: + /// + /// namespace A { + /// void f(); // SemanticDC == LexicalDC == 'namespace A' + /// } + /// void A::f(); // SemanticDC == namespace 'A' + /// // LexicalDC == global namespace + DeclContext *getLexicalDeclContext() { + if (isInSemaDC()) + return getSemanticDC(); + return getMultipleDC()->LexicalDC; + } + const DeclContext *getLexicalDeclContext() const { + return const_cast<Decl*>(this)->getLexicalDeclContext(); + } + + virtual bool isOutOfLine() const { + return getLexicalDeclContext() != getDeclContext(); + } + + /// setDeclContext - Set both the semantic and lexical DeclContext + /// to DC. + void setDeclContext(DeclContext *DC); + + void setLexicalDeclContext(DeclContext *DC); + + // isDefinedOutsideFunctionOrMethod - This predicate returns true if this + // scoped decl is defined outside the current function or method. This is + // roughly global variables and functions, but also handles enums (which could + // be defined inside or outside a function etc). + bool isDefinedOutsideFunctionOrMethod() const; + + /// \brief Retrieves the "canonical" declaration of the given declaration. + virtual Decl *getCanonicalDecl() { return this; } + const Decl *getCanonicalDecl() const { + return const_cast<Decl*>(this)->getCanonicalDecl(); + } + + /// \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. + /// + /// Decl subclasses that can be redeclared should override this method so that + /// Decl::redecl_iterator can iterate over them. + virtual Decl *getNextRedeclaration() { return this; } + +public: + /// \brief Iterates through all the redeclarations of the same decl. + class redecl_iterator { + /// Current - The current declaration. + Decl *Current; + Decl *Starter; + + public: + typedef Decl* value_type; + typedef Decl* reference; + typedef Decl* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + redecl_iterator() : Current(0) { } + explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + redecl_iterator& operator++() { + assert(Current && "Advancing while iterator has reached end"); + // Get either previous decl or latest decl. + Decl *Next = Current->getNextRedeclaration(); + assert(Next && "Should return next redeclaration or itself, never null!"); + Current = (Next != Starter ? Next : 0); + return *this; + } + + redecl_iterator operator++(int) { + redecl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(redecl_iterator x, redecl_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(redecl_iterator x, redecl_iterator y) { + return x.Current != y.Current; + } + }; + + /// \brief Returns iterator for all the redeclarations of the same decl. + /// It will iterate at least once (when this decl is the only one). + redecl_iterator redecls_begin() const { + return redecl_iterator(const_cast<Decl*>(this)); + } + redecl_iterator redecls_end() const { return redecl_iterator(); } + + /// 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. + virtual Stmt* getBody() const { return 0; } + + /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt. + CompoundStmt* getCompoundBody() const; + + /// getBodyRBrace - Gets the right brace of the body, if a body exists. + /// This works whether the body is a CompoundStmt or a CXXTryStmt. + SourceLocation getBodyRBrace() const; + + // global temp stats (until we have a per-module visitor) + static void addDeclKind(Kind k); + static bool CollectingStats(bool Enable = false); + static void PrintStats(); + + /// isTemplateParameter - Determines whether this declaration is a + /// template parameter. + bool isTemplateParameter() const; + + /// isTemplateParameter - Determines whether this declaration is a + /// template parameter pack. + bool isTemplateParameterPack() const; + + /// \brief Whether this declaration is a function or function template. + bool isFunctionOrFunctionTemplate() const; + + /// \brief Changes the namespace of this declaration to reflect that it's + /// the object of a friend declaration. + /// + /// These declarations appear in the lexical context of the friending + /// class, but in the semantic context of the actual entity. This property + /// applies only to a specific decl object; other redeclarations of the + /// same entity may not (and probably don't) share this property. + void setObjectOfFriendDecl(bool PreviouslyDeclared) { + unsigned OldNS = IdentifierNamespace; + assert((OldNS & (IDNS_Tag | IDNS_Ordinary | + IDNS_TagFriend | IDNS_OrdinaryFriend)) && + "namespace includes neither ordinary nor tag"); + assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | + IDNS_TagFriend | IDNS_OrdinaryFriend)) && + "namespace includes other than ordinary or tag"); + + IdentifierNamespace = 0; + if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { + IdentifierNamespace |= IDNS_TagFriend; + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type; + } + + if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { + IdentifierNamespace |= IDNS_OrdinaryFriend; + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary; + } + } + + enum FriendObjectKind { + FOK_None, // not a friend object + FOK_Declared, // a friend of a previously-declared entity + FOK_Undeclared // a friend of a previously-undeclared entity + }; + + /// \brief Determines whether this declaration is the object of a + /// friend declaration and, if so, what kind. + /// + /// There is currently no direct way to find the associated FriendDecl. + FriendObjectKind getFriendObjectKind() const { + unsigned mask + = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); + if (!mask) return FOK_None; + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? + FOK_Declared : FOK_Undeclared); + } + + /// Specifies that this declaration is a C++ overloaded non-member. + void setNonMemberOperator() { + assert(getKind() == Function || getKind() == FunctionTemplate); + assert((IdentifierNamespace & IDNS_Ordinary) && + "visible non-member operators should be in ordinary namespace"); + IdentifierNamespace |= IDNS_NonMemberOperator; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *) { return true; } + static bool classofKind(Kind K) { return true; } + static DeclContext *castToDeclContext(const Decl *); + static Decl *castFromDeclContext(const DeclContext *); + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const; + void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation = 0) const; + static void printGroup(Decl** Begin, unsigned NumDecls, + llvm::raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation = 0); + void dump() const; + +private: + const Attr *getAttrsImpl() const; + +}; + +/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when +/// doing something to a specific decl. +class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { + const Decl *TheDecl; + SourceLocation Loc; + SourceManager &SM; + const char *Message; +public: + PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L, + SourceManager &sm, const char *Msg) + : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} + + virtual void print(llvm::raw_ostream &OS) const; +}; + + +/// DeclContext - This is used only as base class of specific decl types that +/// can act as declaration contexts. These decls are (only the top classes +/// that directly derive from DeclContext are mentioned, not their subclasses): +/// +/// TranslationUnitDecl +/// NamespaceDecl +/// FunctionDecl +/// TagDecl +/// ObjCMethodDecl +/// ObjCContainerDecl +/// LinkageSpecDecl +/// BlockDecl +/// +class DeclContext { + /// DeclKind - This indicates which class this is. + Decl::Kind DeclKind : 8; + + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are lexically + /// part of this context. + mutable bool ExternalLexicalStorage : 1; + + /// \brief Whether this declaration context also has some external + /// storage that contains additional declarations that are visible + /// in this context. + mutable bool ExternalVisibleStorage : 1; + + /// \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; + + /// FirstDecl - The first declaration stored within this declaration + /// context. + mutable Decl *FirstDecl; + + /// LastDecl - The last declaration stored within this declaration + /// context. FIXME: We could probably cache this value somewhere + /// outside of the DeclContext, to reduce the size of DeclContext by + /// another pointer. + mutable Decl *LastDecl; + +protected: + DeclContext(Decl::Kind K) + : DeclKind(K), ExternalLexicalStorage(false), + ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + LastDecl(0) { } + + void DestroyDecls(ASTContext &C); + +public: + ~DeclContext(); + + Decl::Kind getDeclKind() const { + return DeclKind; + } + const char *getDeclKindName() const; + + /// getParent - Returns the containing DeclContext. + DeclContext *getParent() { + return cast<Decl>(this)->getDeclContext(); + } + const DeclContext *getParent() const { + return const_cast<DeclContext*>(this)->getParent(); + } + + /// getLexicalParent - Returns the containing lexical DeclContext. May be + /// different from getParent, e.g.: + /// + /// namespace A { + /// struct S; + /// } + /// struct A::S {}; // getParent() == namespace 'A' + /// // getLexicalParent() == translation unit + /// + DeclContext *getLexicalParent() { + return cast<Decl>(this)->getLexicalDeclContext(); + } + const DeclContext *getLexicalParent() const { + return const_cast<DeclContext*>(this)->getLexicalParent(); + } + + DeclContext *getLookupParent(); + + const DeclContext *getLookupParent() const { + return const_cast<DeclContext*>(this)->getLookupParent(); + } + + ASTContext &getParentASTContext() const { + return cast<Decl>(this)->getASTContext(); + } + + bool isFunctionOrMethod() const { + switch (DeclKind) { + case Decl::Block: + case Decl::ObjCMethod: + return true; + default: + return DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast; + } + } + + bool isFileContext() const { + return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace; + } + + bool isTranslationUnit() const { + return DeclKind == Decl::TranslationUnit; + } + + bool isRecord() const { + return DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast; + } + + bool isNamespace() const { + return DeclKind == Decl::Namespace; + } + + /// \brief Determines whether this context is dependent on a + /// template parameter. + bool isDependentContext() const; + + /// isTransparentContext - Determines whether this context is a + /// "transparent" context, meaning that the members declared in this + /// context are semantically declared in the nearest enclosing + /// non-transparent (opaque) context but are lexically declared in + /// this context. For example, consider the enumerators of an + /// enumeration type: + /// @code + /// enum E { + /// Val1 + /// }; + /// @endcode + /// Here, E is a transparent context, so its enumerator (Val1) will + /// appear (semantically) that it is in the same context of E. + /// Examples of transparent contexts include: enumerations (except for + /// C++0x scoped enums), C++ linkage specifications, and C++0x + /// inline namespaces. + bool isTransparentContext() const; + + /// \brief Determine whether this declaration context is equivalent + /// to the declaration context DC. + bool Equals(DeclContext *DC) { + return DC && this->getPrimaryContext() == DC->getPrimaryContext(); + } + + /// \brief Determine whether this declaration context encloses the + /// declaration context DC. + bool Encloses(DeclContext *DC); + + /// getPrimaryContext - There may be many different + /// declarations of the same entity (including forward declarations + /// of classes, multiple definitions of namespaces, etc.), each with + /// a different set of declarations. This routine returns the + /// "primary" DeclContext structure, which will contain the + /// information needed to perform name lookup into this context. + DeclContext *getPrimaryContext(); + const DeclContext *getPrimaryContext() const { + return const_cast<DeclContext*>(this)->getPrimaryContext(); + } + + /// getLookupContext - Retrieve the innermost non-transparent + /// context of this context, which corresponds to the innermost + /// location from which name lookup can find the entities in this + /// context. + DeclContext *getLookupContext(); + const DeclContext *getLookupContext() const { + return const_cast<DeclContext *>(this)->getLookupContext(); + } + + /// \brief Retrieve the nearest enclosing namespace context. + DeclContext *getEnclosingNamespaceContext(); + const DeclContext *getEnclosingNamespaceContext() const { + return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); + } + + /// 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 + /// 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(); + + /// decl_iterator - Iterates through the declarations stored + /// within this context. + class decl_iterator { + /// Current - The current declaration. + Decl *Current; + + public: + typedef Decl* value_type; + typedef Decl* reference; + typedef Decl* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + decl_iterator() : Current(0) { } + explicit decl_iterator(Decl *C) : Current(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + decl_iterator& operator++() { + Current = Current->getNextDeclInContext(); + return *this; + } + + decl_iterator operator++(int) { + decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(decl_iterator x, decl_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(decl_iterator x, decl_iterator y) { + return x.Current != y.Current; + } + }; + + /// decls_begin/decls_end - Iterate over the declarations stored in + /// this context. + decl_iterator decls_begin() const; + decl_iterator decls_end() const; + bool decls_empty() const; + + /// specific_decl_iterator - Iterates over a subrange of + /// declarations stored in a DeclContext, providing only those that + /// are of type SpecificDecl (or a class derived from it). This + /// iterator is used, for example, to provide iteration over just + /// the fields within a RecordDecl (with SpecificDecl = FieldDecl). + template<typename SpecificDecl> + class specific_decl_iterator { + /// Current - The current, underlying declaration iterator, which + /// will either be NULL or will point to a declaration of + /// type SpecificDecl. + DeclContext::decl_iterator Current; + + /// SkipToNextDecl - Advances the current position up to the next + /// declaration of type SpecificDecl that also meets the criteria + /// required by Acceptable. + void SkipToNextDecl() { + while (*Current && !isa<SpecificDecl>(*Current)) + ++Current; + } + + public: + typedef SpecificDecl* value_type; + typedef SpecificDecl* reference; + typedef SpecificDecl* pointer; + typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type + difference_type; + typedef std::forward_iterator_tag iterator_category; + + specific_decl_iterator() : Current() { } + + /// specific_decl_iterator - Construct a new iterator over a + /// subset of the declarations the range [C, + /// end-of-declarations). If A is non-NULL, it is a pointer to a + /// member function of SpecificDecl that should return true for + /// all of the SpecificDecl instances that will be in the subset + /// of iterators. For example, if you want Objective-C instance + /// methods, SpecificDecl will be ObjCMethodDecl and A will be + /// &ObjCMethodDecl::isInstanceMethod. + explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) { + SkipToNextDecl(); + } + + reference operator*() const { return cast<SpecificDecl>(*Current); } + pointer operator->() const { return cast<SpecificDecl>(*Current); } + + specific_decl_iterator& operator++() { + ++Current; + SkipToNextDecl(); + return *this; + } + + specific_decl_iterator operator++(int) { + specific_decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + 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) { + return x.Current != y.Current; + } + }; + + /// \brief Iterates over a filtered subrange of declarations stored + /// in a DeclContext. + /// + /// This iterator visits only those declarations that are of type + /// SpecificDecl (or a class derived from it) and that meet some + /// additional run-time criteria. This iterator is used, for + /// example, to provide access to the instance methods within an + /// Objective-C interface (with SpecificDecl = ObjCMethodDecl and + /// Acceptable = ObjCMethodDecl::isInstanceMethod). + template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const> + class filtered_decl_iterator { + /// Current - The current, underlying declaration iterator, which + /// will either be NULL or will point to a declaration of + /// type SpecificDecl. + DeclContext::decl_iterator Current; + + /// SkipToNextDecl - Advances the current position up to the next + /// declaration of type SpecificDecl that also meets the criteria + /// required by Acceptable. + void SkipToNextDecl() { + while (*Current && + (!isa<SpecificDecl>(*Current) || + (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)()))) + ++Current; + } + + public: + typedef SpecificDecl* value_type; + typedef SpecificDecl* reference; + typedef SpecificDecl* pointer; + typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type + difference_type; + typedef std::forward_iterator_tag iterator_category; + + filtered_decl_iterator() : Current() { } + + /// specific_decl_iterator - Construct a new iterator over a + /// subset of the declarations the range [C, + /// end-of-declarations). If A is non-NULL, it is a pointer to a + /// member function of SpecificDecl that should return true for + /// all of the SpecificDecl instances that will be in the subset + /// of iterators. For example, if you want Objective-C instance + /// methods, SpecificDecl will be ObjCMethodDecl and A will be + /// &ObjCMethodDecl::isInstanceMethod. + explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) { + SkipToNextDecl(); + } + + reference operator*() const { return cast<SpecificDecl>(*Current); } + pointer operator->() const { return cast<SpecificDecl>(*Current); } + + filtered_decl_iterator& operator++() { + ++Current; + SkipToNextDecl(); + return *this; + } + + filtered_decl_iterator operator++(int) { + filtered_decl_iterator tmp(*this); + ++(*this); + return tmp; + } + + 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) { + return x.Current != y.Current; + } + }; + + /// @brief Add the declaration D into this context. + /// + /// This routine should be invoked when the declaration D has first + /// been declared, to place D into the context where it was + /// (lexically) defined. Every declaration must be added to one + /// (and only one!) context, where it can be visited via + /// [decls_begin(), decls_end()). Once a declaration has been added + /// to its lexical context, the corresponding DeclContext owns the + /// declaration. + /// + /// If D is also a NamedDecl, it will be made visible within its + /// semantic context via makeDeclVisibleInContext. + void addDecl(Decl *D); + + /// @brief Add the declaration D to this context without modifying + /// any lookup tables. + /// + /// This is useful for some operations in dependent contexts where + /// the semantic context might not be dependent; this basically + /// only happens with friends. + void addHiddenDecl(Decl *D); + + /// @brief Removes a declaration from this context. + void removeDecl(Decl *D); + + /// lookup_iterator - An iterator that provides access to the results + /// of looking up a name within this context. + typedef NamedDecl **lookup_iterator; + + /// lookup_const_iterator - An iterator that provides non-mutable + /// access to the results of lookup up a name within this context. + typedef NamedDecl * const * lookup_const_iterator; + + typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; + typedef std::pair<lookup_const_iterator, lookup_const_iterator> + lookup_const_result; + + /// lookup - Find the declarations (if any) with the given Name in + /// this context. Returns a range of iterators that contains all of + /// the declarations with this name, with object, function, member, + /// and enumerator names preceding any tag name. Note that this + /// routine will not look into parent contexts. + lookup_result lookup(DeclarationName Name); + lookup_const_result lookup(DeclarationName Name) const; + + /// @brief Makes a declaration visible within this context. + /// + /// This routine makes the declaration D visible to name lookup + /// within this context and, if this is a transparent context, + /// within its parent contexts up to the first enclosing + /// non-transparent context. Making a declaration visible within a + /// context does not transfer ownership of a declaration, and a + /// declaration can be visible in many contexts that aren't its + /// lexical context. + /// + /// If D is a redeclaration of an existing declaration that is + /// 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); + + /// udir_iterator - Iterates through the using-directives stored + /// within this context. + typedef UsingDirectiveDecl * const * udir_iterator; + + typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range; + + udir_iterator_range getUsingDirectives() const; + + udir_iterator using_directives_begin() const { + return getUsingDirectives().first; + } + + udir_iterator using_directives_end() const { + return getUsingDirectives().second; + } + + // These are all defined in DependentDiagnostic.h. + class ddiag_iterator; + inline ddiag_iterator ddiag_begin() const; + inline ddiag_iterator ddiag_end() const; + + // Low-level accessors + + /// \brief Retrieve the internal representation of the lookup structure. + StoredDeclsMap* getLookupPtr() const { return LookupPtr; } + + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are lexically in this context. + bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations lexically in this context. + void setHasExternalLexicalStorage(bool ES = true) { + ExternalLexicalStorage = ES; + } + + /// \brief Whether this DeclContext has external storage containing + /// additional declarations that are visible in this context. + bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; } + + /// \brief State whether this DeclContext has external storage for + /// declarations visible in this context. + void setHasExternalVisibleStorage(bool ES = true) { + ExternalVisibleStorage = ES; + } + + static bool classof(const Decl *D); + static bool classof(const DeclContext *D) { return true; } +#define DECL_CONTEXT(Name) \ + static bool classof(const Name##Decl *D) { return true; } +#include "clang/AST/DeclNodes.def" + + void dumpDeclContext() const; + +private: + void LoadLexicalDeclsFromExternalStorage() const; + void LoadVisibleDeclsFromExternalStorage() const; + + friend class DependentDiagnostic; + StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; + + void buildLookup(DeclContext *DCtx); + void makeDeclVisibleInContextImpl(NamedDecl *D); +}; + +inline bool Decl::isTemplateParameter() const { + return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm || + getKind() == TemplateTemplateParm; +} + + +// Specialization selected when ToTy is not a known subclass of DeclContext. +template <class ToTy, + bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> +struct cast_convert_decl_context { + static const ToTy *doit(const DeclContext *Val) { + return static_cast<const ToTy*>(Decl::castFromDeclContext(Val)); + } + + static ToTy *doit(DeclContext *Val) { + return static_cast<ToTy*>(Decl::castFromDeclContext(Val)); + } +}; + +// Specialization selected when ToTy is a known subclass of DeclContext. +template <class ToTy> +struct cast_convert_decl_context<ToTy, true> { + static const ToTy *doit(const DeclContext *Val) { + return static_cast<const ToTy*>(Val); + } + + static ToTy *doit(DeclContext *Val) { + return static_cast<ToTy*>(Val); + } +}; + + +} // end clang. + +namespace llvm { + +/// isa<T>(DeclContext*) +template<class ToTy> +struct isa_impl_wrap<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> { + static bool doit(const ::clang::DeclContext &Val) { + return ToTy::classofKind(Val.getDeclKind()); + } +}; +template<class ToTy> +struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext> + : public isa_impl_wrap<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> {}; + +/// cast<T>(DeclContext*) +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext,const ::clang::DeclContext> { + static const ToTy &doit(const ::clang::DeclContext &Val) { + return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> { + static ToTy &doit(::clang::DeclContext &Val) { + return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, + const ::clang::DeclContext*, const ::clang::DeclContext*> { + static const ToTy *doit(const ::clang::DeclContext *Val) { + return ::clang::cast_convert_decl_context<ToTy>::doit(Val); + } +}; +template<class ToTy> +struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> { + static ToTy *doit(::clang::DeclContext *Val) { + return ::clang::cast_convert_decl_context<ToTy>::doit(Val); + } +}; + +/// Implement cast_convert_val for Decl -> DeclContext conversions. +template<class FromTy> +struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> { + static ::clang::DeclContext &doit(const FromTy &Val) { + return *FromTy::castToDeclContext(&Val); + } +}; + +template<class FromTy> +struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> { + static ::clang::DeclContext *doit(const FromTy *Val) { + return FromTy::castToDeclContext(Val); + } +}; + +template<class FromTy> +struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> { + static const ::clang::DeclContext &doit(const FromTy &Val) { + return *FromTy::castToDeclContext(&Val); + } +}; + +template<class FromTy> +struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> { + static const ::clang::DeclContext *doit(const FromTy *Val) { + return FromTy::castToDeclContext(Val); + } +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h new file mode 100644 index 0000000..c19c200 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h @@ -0,0 +1,2111 @@ +//===-- DeclCXX.h - Classes for representing C++ declarations -*- 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 C++ Decl subclasses, other than those for +// templates (in DeclTemplate.h) and friends (in DeclFriend.h). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLCXX_H +#define LLVM_CLANG_AST_DECLCXX_H + +#include "clang/AST/Expr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/UnresolvedSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace clang { + +class ClassTemplateDecl; +class ClassTemplateSpecializationDecl; +class CXXBasePath; +class CXXBasePaths; +class CXXConstructorDecl; +class CXXConversionDecl; +class CXXDestructorDecl; +class CXXMethodDecl; +class CXXRecordDecl; +class CXXMemberLookupCriteria; +class CXXFinalOverriderMap; +class FriendDecl; + +/// \brief Represents any kind of function declaration, whether it is a +/// concrete function or a function template. +class AnyFunctionDecl { + NamedDecl *Function; + + AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } + +public: + AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } + AnyFunctionDecl(FunctionTemplateDecl *FTD); + + /// \brief Implicily converts any function or function template into a + /// named declaration. + operator NamedDecl *() const { return Function; } + + /// \brief Retrieve the underlying function or function template. + NamedDecl *get() const { return Function; } + + static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { + return AnyFunctionDecl(ND); + } +}; + +} // end namespace clang + +namespace llvm { + /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from + /// AnyFunctionDecl to any function or function template declaration. + template<> struct simplify_type<const ::clang::AnyFunctionDecl> { + typedef ::clang::NamedDecl* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) { + return Val; + } + }; + template<> struct simplify_type< ::clang::AnyFunctionDecl> + : public simplify_type<const ::clang::AnyFunctionDecl> {}; + + // Provide PointerLikeTypeTraits for non-cvr pointers. + template<> + class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { + public: + static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) { + return F.get(); + } + static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { + return ::clang::AnyFunctionDecl::getFromNamedDecl( + static_cast< ::clang::NamedDecl*>(P)); + } + + enum { NumLowBitsAvailable = 2 }; + }; + +} // end namespace llvm + +namespace clang { + +/// CXXBaseSpecifier - A base class of a C++ class. +/// +/// Each CXXBaseSpecifier represents a single, direct base class (or +/// struct) of a C++ class (or struct). It specifies the type of that +/// base class, whether it is a virtual or non-virtual base, and what +/// level of access (public, protected, private) is used for the +/// derivation. For example: +/// +/// @code +/// class A { }; +/// class B { }; +/// class C : public virtual A, protected B { }; +/// @endcode +/// +/// In this code, C will have two CXXBaseSpecifiers, one for "public +/// virtual A" and the other for "protected B". +class CXXBaseSpecifier { + /// Range - The source code range that covers the full base + /// specifier, including the "virtual" (if present) and access + /// specifier (if present). + // FIXME: Move over to a TypeLoc! + SourceRange Range; + + /// Virtual - Whether this is a virtual base class or not. + bool Virtual : 1; + + /// BaseOfClass - Whether this is the base of a class (true) or of a + /// struct (false). This determines the mapping from the access + /// specifier as written in the source code to the access specifier + /// used for semantic analysis. + bool BaseOfClass : 1; + + /// Access - Access specifier as written in the source code (which + /// may be AS_none). The actual type of data stored here is an + /// AccessSpecifier, but we use "unsigned" here to work around a + /// VC++ bug. + unsigned Access : 2; + + /// BaseType - The type of the base class. This will be a class or + /// struct (or a typedef of such). + QualType BaseType; + +public: + CXXBaseSpecifier() { } + + CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T) + : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { } + + /// getSourceRange - Retrieves the source range that contains the + /// entire base specifier. + SourceRange getSourceRange() const { return Range; } + + /// isVirtual - Determines whether the base class is a virtual base + /// class (or not). + bool isVirtual() const { return Virtual; } + + /// \brief Determine whether this base class if a base of a class declared + /// with the 'class' keyword (vs. one declared with the 'struct' keyword). + bool isBaseOfClass() const { return BaseOfClass; } + + /// getAccessSpecifier - Returns the access specifier for this base + /// specifier. This is the actual base specifier as used for + /// semantic analysis, so the result can never be AS_none. To + /// retrieve the access specifier as written in the source code, use + /// getAccessSpecifierAsWritten(). + AccessSpecifier getAccessSpecifier() const { + if ((AccessSpecifier)Access == AS_none) + return BaseOfClass? AS_private : AS_public; + else + return (AccessSpecifier)Access; + } + + /// getAccessSpecifierAsWritten - Retrieves the access specifier as + /// written in the source code (which may mean that no access + /// specifier was explicitly written). Use getAccessSpecifier() to + /// retrieve the access specifier for use in semantic analysis. + AccessSpecifier getAccessSpecifierAsWritten() const { + return (AccessSpecifier)Access; + } + + /// getType - Retrieves the type of the base class. This type will + /// always be an unqualified class type. + QualType getType() const { return BaseType; } +}; + +/// CXXRecordDecl - Represents a C++ struct/union/class. +/// FIXME: This class will disappear once we've properly taught RecordDecl +/// to deal with C++-specific things. +class CXXRecordDecl : public RecordDecl { + + friend void TagDecl::startDefinition(); + + struct DefinitionData { + DefinitionData(CXXRecordDecl *D); + + /// UserDeclaredConstructor - True when this class has a + /// user-declared constructor. + bool UserDeclaredConstructor : 1; + + /// UserDeclaredCopyConstructor - True when this class has a + /// user-declared copy constructor. + bool UserDeclaredCopyConstructor : 1; + + /// UserDeclaredCopyAssignment - True when this class has a + /// user-declared copy assignment operator. + bool UserDeclaredCopyAssignment : 1; + + /// UserDeclaredDestructor - True when this class has a + /// user-declared destructor. + bool UserDeclaredDestructor : 1; + + /// Aggregate - True when this class is an aggregate. + bool Aggregate : 1; + + /// PlainOldData - True when this class is a POD-type. + bool PlainOldData : 1; + + /// Empty - true when this class is empty for traits purposes, + /// i.e. has no data members other than 0-width bit-fields, has no + /// virtual function/base, and doesn't inherit from a non-empty + /// class. Doesn't take union-ness into account. + bool Empty : 1; + + /// Polymorphic - True when this class is polymorphic, i.e. has at + /// least one virtual member or derives from a polymorphic class. + bool Polymorphic : 1; + + /// Abstract - True when this class is abstract, i.e. has at least + /// one pure virtual function, (that can come from a base class). + bool Abstract : 1; + + /// HasTrivialConstructor - True when this class has a trivial constructor. + /// + /// C++ [class.ctor]p5. A constructor is trivial if it is an + /// implicitly-declared default constructor and if: + /// * its class has no virtual functions and no virtual base classes, and + /// * all the direct base classes of its class have trivial constructors, and + /// * for all the nonstatic data members of its class that are of class type + /// (or array thereof), each such class has a trivial constructor. + bool HasTrivialConstructor : 1; + + /// HasTrivialCopyConstructor - True when this class has a trivial copy + /// constructor. + /// + /// C++ [class.copy]p6. A copy constructor for class X is trivial + /// if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy constructor, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy constructor; + /// otherwise the copy constructor is non-trivial. + bool HasTrivialCopyConstructor : 1; + + /// HasTrivialCopyAssignment - True when this class has a trivial copy + /// assignment operator. + /// + /// C++ [class.copy]p11. A copy assignment operator for class X is + /// trivial if it is implicitly declared and if + /// * class X has no virtual functions and no virtual base classes, and + /// * each direct base class of X has a trivial copy assignment operator, and + /// * for all the nonstatic data members of X that are of class type (or + /// array thereof), each such class type has a trivial copy assignment + /// operator; + /// otherwise the copy assignment operator is non-trivial. + bool HasTrivialCopyAssignment : 1; + + /// HasTrivialDestructor - True when this class has a trivial destructor. + /// + /// C++ [class.dtor]p3. A destructor is trivial if it is an + /// implicitly-declared destructor and if: + /// * all of the direct base classes of its class have trivial destructors + /// and + /// * for all of the non-static data members of its class that are of class + /// type (or array thereof), each such class has a trivial destructor. + bool HasTrivialDestructor : 1; + + /// ComputedVisibleConversions - True when visible conversion functions are + /// already computed and are available. + bool ComputedVisibleConversions : 1; + + /// Bases - Base classes of this class. + /// FIXME: This is wasted space for a union. + CXXBaseSpecifier *Bases; + + /// NumBases - The number of base class specifiers in Bases. + unsigned NumBases; + + /// VBases - direct and indirect virtual base classes of this class. + CXXBaseSpecifier *VBases; + + /// NumVBases - The number of virtual base class specifiers in VBases. + unsigned NumVBases; + + /// Conversions - Overload set containing the conversion functions + /// of this C++ class (but not its inherited conversion + /// functions). Each of the entries in this overload set is a + /// CXXConversionDecl. + UnresolvedSet<4> Conversions; + + /// VisibleConversions - Overload set containing the conversion + /// functions of this C++ class and all those inherited conversion + /// functions that are visible in this class. Each of the entries + /// in this overload set is a CXXConversionDecl or a + /// FunctionTemplateDecl. + UnresolvedSet<4> VisibleConversions; + + /// Definition - The declaration which defines this record. + CXXRecordDecl *Definition; + + /// FirstFriend - The first friend declaration in this class, or + /// null if there aren't any. This is actually currently stored + /// in reverse order. + FriendDecl *FirstFriend; + + } *DefinitionData; + + struct DefinitionData &data() { + assert(DefinitionData && "queried property of class with no definition"); + return *DefinitionData; + } + + const struct DefinitionData &data() const { + assert(DefinitionData && "queried property of class with no definition"); + return *DefinitionData; + } + + /// \brief The template or declaration that this declaration + /// describes or was instantiated from, respectively. + /// + /// For non-templates, this value will be NULL. For record + /// 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 + /// instantiated or specialized. + llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> + TemplateOrInstantiation; + +#ifndef NDEBUG + void CheckConversionFunction(NamedDecl *D); +#endif + +protected: + CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl, + SourceLocation TKL = SourceLocation()); + + ~CXXRecordDecl(); + +public: + /// base_class_iterator - Iterator that traverses the base classes + /// of a class. + typedef CXXBaseSpecifier* base_class_iterator; + + /// base_class_const_iterator - Iterator that traverses the base + /// classes of a class. + typedef const CXXBaseSpecifier* base_class_const_iterator; + + /// reverse_base_class_iterator = Iterator that traverses the base classes + /// of a class in reverse order. + typedef std::reverse_iterator<base_class_iterator> + reverse_base_class_iterator; + + /// reverse_base_class_iterator = Iterator that traverses the base classes + /// of a class in reverse order. + typedef std::reverse_iterator<base_class_const_iterator> + reverse_base_class_const_iterator; + + virtual CXXRecordDecl *getCanonicalDecl() { + return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); + } + virtual const CXXRecordDecl *getCanonicalDecl() const { + return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); + } + + CXXRecordDecl *getDefinition() const { + if (!DefinitionData) return 0; + return data().Definition; + } + + bool hasDefinition() const { return DefinitionData != 0; } + + static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + SourceLocation TKL = SourceLocation(), + CXXRecordDecl* PrevDecl=0, + bool DelayTypeCreation = false); + + virtual void Destroy(ASTContext& C); + + bool isDynamicClass() const { + return data().Polymorphic || data().NumVBases != 0; + } + + /// setBases - Sets the base classes of this struct or class. + void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); + + /// getNumBases - Retrieves the number of base classes of this + /// class. + unsigned getNumBases() const { return data().NumBases; } + + base_class_iterator bases_begin() { return data().Bases; } + base_class_const_iterator bases_begin() const { return data().Bases; } + base_class_iterator bases_end() { return bases_begin() + data().NumBases; } + base_class_const_iterator bases_end() const { + return bases_begin() + data().NumBases; + } + reverse_base_class_iterator bases_rbegin() { + return reverse_base_class_iterator(bases_end()); + } + reverse_base_class_const_iterator bases_rbegin() const { + return reverse_base_class_const_iterator(bases_end()); + } + reverse_base_class_iterator bases_rend() { + return reverse_base_class_iterator(bases_begin()); + } + reverse_base_class_const_iterator bases_rend() const { + return reverse_base_class_const_iterator(bases_begin()); + } + + /// getNumVBases - Retrieves the number of virtual base classes of this + /// class. + unsigned getNumVBases() const { return data().NumVBases; } + + base_class_iterator vbases_begin() { return data().VBases; } + base_class_const_iterator vbases_begin() const { return data().VBases; } + base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; } + base_class_const_iterator vbases_end() const { + return vbases_begin() + data().NumVBases; + } + reverse_base_class_iterator vbases_rbegin() { + return reverse_base_class_iterator(vbases_end()); + } + reverse_base_class_const_iterator vbases_rbegin() const { + return reverse_base_class_const_iterator(vbases_end()); + } + reverse_base_class_iterator vbases_rend() { + return reverse_base_class_iterator(vbases_begin()); + } + reverse_base_class_const_iterator vbases_rend() const { + return reverse_base_class_const_iterator(vbases_begin()); + } + + /// \brief Determine whether this class has any dependent base classes. + bool hasAnyDependentBases() const; + + /// Iterator access to method members. The method iterator visits + /// all method members of the class, including non-instance methods, + /// special methods, etc. + typedef specific_decl_iterator<CXXMethodDecl> method_iterator; + + /// method_begin - Method begin iterator. Iterates in the order the methods + /// were declared. + method_iterator method_begin() const { + return method_iterator(decls_begin()); + } + /// method_end - Method end iterator. + method_iterator method_end() const { + return method_iterator(decls_end()); + } + + /// Iterator access to constructor members. + typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator; + + ctor_iterator ctor_begin() const { + return ctor_iterator(decls_begin()); + } + ctor_iterator ctor_end() const { + return ctor_iterator(decls_end()); + } + + /// An iterator over friend declarations. All of these are defined + /// in DeclFriend.h. + class friend_iterator; + friend_iterator friend_begin() const; + friend_iterator friend_end() const; + void pushFriendDecl(FriendDecl *FD); + + /// Determines whether this record has any friends. + bool hasFriends() const { + return data().FirstFriend != 0; + } + + /// hasConstCopyConstructor - Determines whether this class has a + /// copy constructor that accepts a const-qualified argument. + bool hasConstCopyConstructor(ASTContext &Context) const; + + /// getCopyConstructor - Returns the copy constructor for this class + CXXConstructorDecl *getCopyConstructor(ASTContext &Context, + unsigned TypeQuals) const; + + /// hasConstCopyAssignment - Determines whether this class has a + /// copy assignment operator that accepts a const-qualified argument. + /// It returns its decl in MD if found. + bool hasConstCopyAssignment(ASTContext &Context, + const CXXMethodDecl *&MD) const; + + /// addedConstructor - Notify the class that another constructor has + /// been added. This routine helps maintain information about the + /// class based on which constructors have been added. + void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl); + + /// hasUserDeclaredConstructor - Whether this class has any + /// user-declared constructors. When true, a default constructor + /// will not be implicitly declared. + bool hasUserDeclaredConstructor() const { + return data().UserDeclaredConstructor; + } + + /// hasUserDeclaredCopyConstructor - Whether this class has a + /// user-declared copy constructor. When false, a copy constructor + /// will be implicitly declared. + bool hasUserDeclaredCopyConstructor() const { + return data().UserDeclaredCopyConstructor; + } + + /// addedAssignmentOperator - Notify the class that another assignment + /// operator has been added. This routine helps maintain information about the + /// class based on which operators have been added. + void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl); + + /// hasUserDeclaredCopyAssignment - Whether this class has a + /// user-declared copy assignment operator. When false, a copy + /// assigment operator will be implicitly declared. + bool hasUserDeclaredCopyAssignment() const { + return data().UserDeclaredCopyAssignment; + } + + /// hasUserDeclaredDestructor - Whether this class has a + /// user-declared destructor. When false, a destructor will be + /// implicitly declared. + bool hasUserDeclaredDestructor() const { + return data().UserDeclaredDestructor; + } + + /// setUserDeclaredDestructor - Set whether this class has a + /// user-declared destructor. If not set by the time the class is + /// fully defined, a destructor will be implicitly declared. + void setUserDeclaredDestructor(bool UCD) { + data().UserDeclaredDestructor = UCD; + } + + /// getConversions - Retrieve the overload set containing all of the + /// conversion functions in this class. + UnresolvedSetImpl *getConversionFunctions() { + return &data().Conversions; + } + const UnresolvedSetImpl *getConversionFunctions() const { + return &data().Conversions; + } + + typedef UnresolvedSetImpl::iterator conversion_iterator; + conversion_iterator conversion_begin() const { + return getConversionFunctions()->begin(); + } + conversion_iterator conversion_end() const { + return getConversionFunctions()->end(); + } + + /// Replaces a conversion function with a new declaration. + /// + /// Returns true if the old conversion was found. + bool replaceConversion(const NamedDecl* Old, NamedDecl *New) { + return getConversionFunctions()->replace(Old, New); + } + + /// Removes a conversion function from this class. The conversion + /// function must currently be a member of this class. Furthermore, + /// this class must currently be in the process of being defined. + void removeConversion(const NamedDecl *Old); + + /// getVisibleConversionFunctions - get all conversion functions visible + /// in current class; including conversion function templates. + const UnresolvedSetImpl *getVisibleConversionFunctions(); + + /// addConversionFunction - Registers a conversion function which + /// this class declares directly. + void addConversionFunction(NamedDecl *Decl) { +#ifndef NDEBUG + CheckConversionFunction(Decl); +#endif + + // We intentionally don't use the decl's access here because it + // hasn't been set yet. That's really just a misdesign in Sema. + data().Conversions.addDecl(Decl); + } + + /// isAggregate - Whether this class is an aggregate (C++ + /// [dcl.init.aggr]), which is a class with no user-declared + /// constructors, no private or protected non-static data members, + /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). + bool isAggregate() const { return data().Aggregate; } + + /// setAggregate - Set whether this class is an aggregate (C++ + /// [dcl.init.aggr]). + void setAggregate(bool Agg) { data().Aggregate = Agg; } + + /// setMethodAsVirtual - Make input method virtual and set the necesssary + /// special function bits and other bits accordingly. + void setMethodAsVirtual(FunctionDecl *Method); + + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class + /// that is an aggregate that has no non-static non-POD data members, no + /// reference data members, no user-defined copy assignment operator and no + /// user-defined destructor. + bool isPOD() const { return data().PlainOldData; } + + /// setPOD - Set whether this class is a POD-type (C++ [class]p4). + void setPOD(bool POD) { data().PlainOldData = POD; } + + /// 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 + /// a check for union-ness. + bool isEmpty() const { return data().Empty; } + + /// Set whether this class is empty (C++0x [meta.unary.prop]) + void setEmpty(bool Emp) { data().Empty = Emp; } + + /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), + /// which means that the class contains or inherits a virtual function. + bool isPolymorphic() const { return data().Polymorphic; } + + /// setPolymorphic - Set whether this class is polymorphic (C++ + /// [class.virtual]). + void setPolymorphic(bool Poly) { data().Polymorphic = Poly; } + + /// isAbstract - Whether this class is abstract (C++ [class.abstract]), + /// which means that the class contains or inherits a pure virtual function. + bool isAbstract() const { return data().Abstract; } + + /// setAbstract - Set whether this class is abstract (C++ [class.abstract]) + void setAbstract(bool Abs) { data().Abstract = Abs; } + + // hasTrivialConstructor - Whether this class has a trivial constructor + // (C++ [class.ctor]p5) + bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } + + // setHasTrivialConstructor - Set whether this class has a trivial constructor + // (C++ [class.ctor]p5) + void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; } + + // hasTrivialCopyConstructor - Whether this class has a trivial copy + // constructor (C++ [class.copy]p6) + bool hasTrivialCopyConstructor() const { + return data().HasTrivialCopyConstructor; + } + + // setHasTrivialCopyConstructor - Set whether this class has a trivial + // copy constructor (C++ [class.copy]p6) + void setHasTrivialCopyConstructor(bool TC) { + data().HasTrivialCopyConstructor = TC; + } + + // hasTrivialCopyAssignment - Whether this class has a trivial copy + // assignment operator (C++ [class.copy]p11) + bool hasTrivialCopyAssignment() const { + return data().HasTrivialCopyAssignment; + } + + // setHasTrivialCopyAssignment - Set whether this class has a + // trivial copy assignment operator (C++ [class.copy]p11) + void setHasTrivialCopyAssignment(bool TC) { + data().HasTrivialCopyAssignment = TC; + } + + // hasTrivialDestructor - Whether this class has a trivial destructor + // (C++ [class.dtor]p3) + bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + + // setHasTrivialDestructor - Set whether this class has a trivial destructor + // (C++ [class.dtor]p3) + void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; } + + /// \brief If this record is an instantiation of a member class, + /// retrieves the member class from which it was instantiated. + /// + /// This routine will return non-NULL for (non-templated) member + /// classes of class templates. For example, given: + /// + /// \code + /// template<typename T> + /// struct X { + /// struct A { }; + /// }; + /// \endcode + /// + /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl + /// whose parent is the class template specialization X<int>. For + /// this declaration, getInstantiatedFromMemberClass() will return + /// the CXXRecordDecl X<T>::A. When a complete definition of + /// 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, + TemplateSpecializationKind TSK); + + /// \brief Retrieves the class template that is described by this + /// class declaration. + /// + /// Every class template is represented as a ClassTemplateDecl and a + /// CXXRecordDecl. The former contains template properties (such as + /// the template parameter lists) while the latter contains the + /// actual description of the template's + /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the + /// CXXRecordDecl that from a ClassTemplateDecl, while + /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from + /// a CXXRecordDecl. + ClassTemplateDecl *getDescribedClassTemplate() const { + return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>(); + } + + void setDescribedClassTemplate(ClassTemplateDecl *Template) { + TemplateOrInstantiation = Template; + } + + /// \brief Determine whether this particular class is a specialization or + /// 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); + + /// getDefaultConstructor - Returns the default constructor for this class + CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); + + /// getDestructor - Returns the destructor decl for this class. + CXXDestructorDecl *getDestructor(ASTContext &Context) const; + + /// isLocalClass - If the class is a local class [class.local], returns + /// the enclosing function declaration. + const FunctionDecl *isLocalClass() const { + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext())) + return RD->isLocalClass(); + + return dyn_cast<FunctionDecl>(getDeclContext()); + } + + /// \brief Determine whether this class is derived from the class \p Base. + /// + /// This routine only determines whether this class is derived from \p Base, + /// but does not account for factors that may make a Derived -> Base class + /// ill-formed, such as private/protected inheritance or multiple, ambiguous + /// base class subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \returns true if this class is derived from Base, false otherwise. + bool isDerivedFrom(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, + /// but does not account for factors that may make a Derived -> Base class + /// ill-formed, such as private/protected inheritance or multiple, ambiguous + /// base class subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \param Paths will contain the paths taken from the current class to the + /// given \p Base class. + /// + /// \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 + bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; + + /// \brief Determine whether this class is virtually derived from + /// the class \p Base. + /// + /// This routine only determines whether this class is virtually + /// derived from \p Base, but does not account for factors that may + /// make a Derived -> Base class ill-formed, such as + /// private/protected inheritance or multiple, ambiguous base class + /// subobjects. + /// + /// \param Base the base class we are searching for. + /// + /// \returns true if this class is virtually derived from Base, + /// false otherwise. + bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const; + + /// \brief Determine whether this class is provably not derived from + /// the type \p Base. + bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const; + + /// \brief Function type used by forallBases() as a callback. + /// + /// \param Base the definition of the base class + /// + /// \returns true if this base matched the search criteria + typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition, + void *UserData); + + /// \brief Determines if the given callback holds for all the direct + /// or indirect base classes of this type. + /// + /// 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 + /// specific base class subobject matches the lookup criteria. + /// + /// \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 + /// base named by the \p Specifier. + /// + /// \param UserData a single pointer to user-specified data, provided to + /// lookupInBases(). + /// + /// \returns true if this base matched the search criteria, false otherwise. + 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 + /// classes meeting some search criteria, walking all base class subobjects + /// 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. + /// + /// \param BaseMatches callback function used to determine whether a given + /// base matches the user-defined search criteria. + /// + /// \param UserData user data pointer that will be provided to \p BaseMatches. + /// + /// \param Paths used to record the paths from this class to its base class + /// subobjects that match the search criteria. + /// + /// \returns true if there exists any path from this class to a base class + /// 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. + /// + /// This callback can be used with \c lookupInBases() to determine whether + /// a given derived class has is a base class subobject of a particular type. + /// The user data pointer should refer to the canonical CXXRecordDecl of the + /// base class that we are searching for. + static bool FindBaseClass(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *BaseRecord); + + /// \brief Base-class lookup callback that determines whether the + /// given base class specifier refers to a specific class + /// declaration and describes virtual derivation. + /// + /// This callback can be used with \c lookupInBases() to determine + /// whether a given derived class has is a virtual base class + /// subobject of a particular type. The user data pointer should + /// refer to the canonical CXXRecordDecl of the base class that we + /// are searching for. + static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *BaseRecord); + + /// \brief Base-class lookup callback that determines whether there exists + /// a tag with the given name. + /// + /// This callback can be used with \c lookupInBases() to find tag members + /// of the given name within a C++ class hierarchy. The user data pointer + /// is an opaque \c DeclarationName pointer. + static bool FindTagMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *Name); + + /// \brief Base-class lookup callback that determines whether there exists + /// a member with the given name. + /// + /// This callback can be used with \c lookupInBases() to find members + /// of the given name within a C++ class hierarchy. The user data pointer + /// 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. + /// + /// This callback can be used with \c lookupInBases() to find membes of + /// the given name within a C++ class hierarchy that can occur within + /// nested-name-specifiers. + static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData); + + /// \brief Retrieve the final overriders for each virtual member + /// function in the class hierarchy where this class is the + /// most-derived class in the class hierarchy. + void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const; + + /// viewInheritance - Renders and displays an inheritance diagram + /// for this C++ class and all of its base classes (transitively) using + /// GraphViz. + void viewInheritance(ASTContext& Context) const; + + /// MergeAccess - Calculates the access of a decl that is reached + /// along a path. + static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, + AccessSpecifier DeclAccess) { + assert(DeclAccess != AS_none); + if (DeclAccess == AS_private) return AS_none; + return (PathAccess > DeclAccess ? PathAccess : DeclAccess); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == CXXRecord || + K == ClassTemplateSpecialization || + K == ClassTemplatePartialSpecialization; + } + static bool classof(const CXXRecordDecl *D) { return true; } + static bool classof(const ClassTemplateSpecializationDecl *D) { + return true; + } +}; + +/// CXXMethodDecl - Represents a static or instance method of a +/// struct/union/class. +class CXXMethodDecl : public FunctionDecl { +protected: + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + bool isStatic, StorageClass SCAsWritten, bool isInline) + : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), + SCAsWritten, isInline) {} + +public: + static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, TypeSourceInfo *TInfo, + bool isStatic = false, + StorageClass SCAsWritten = FunctionDecl::None, + bool isInline = false); + + bool isStatic() const { return getStorageClass() == Static; } + bool isInstance() const { return !isStatic(); } + + bool isVirtual() const { + CXXMethodDecl *CD = + cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); + + if (CD->isVirtualAsWritten()) + return true; + + return (CD->begin_overridden_methods() != CD->end_overridden_methods()); + } + + /// \brief Determine whether this is a usual deallocation function + /// (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; + + const CXXMethodDecl *getCanonicalDecl() const { + return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); + } + CXXMethodDecl *getCanonicalDecl() { + return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); + } + + /// + void addOverriddenMethod(const CXXMethodDecl *MD); + + typedef const CXXMethodDecl ** method_iterator; + + method_iterator begin_overridden_methods() const; + method_iterator end_overridden_methods() const; + + /// getParent - Returns the parent of this method declaration, which + /// is the class in which this method is defined. + const CXXRecordDecl *getParent() const { + return cast<CXXRecordDecl>(FunctionDecl::getParent()); + } + + /// getParent - Returns the parent of this method declaration, which + /// is the class in which this method is defined. + CXXRecordDecl *getParent() { + return const_cast<CXXRecordDecl *>( + cast<CXXRecordDecl>(FunctionDecl::getParent())); + } + + /// getThisType - Returns the type of 'this' pointer. + /// Should only be called for instance methods. + QualType getThisType(ASTContext &C) const; + + unsigned getTypeQualifiers() const { + return getType()->getAs<FunctionProtoType>()->getTypeQuals(); + } + + bool hasInlineBody() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const CXXMethodDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= CXXMethod && K <= CXXConversion; + } +}; + +/// CXXBaseOrMemberInitializer - Represents a C++ base or member +/// initializer, which is part of a constructor initializer that +/// initializes one non-static member variable or one base class. For +/// example, in the following, both 'A(a)' and 'f(3.14159)' are member +/// initializers: +/// +/// @code +/// class A { }; +/// class B : public A { +/// float f; +/// public: +/// B(A& a) : A(a), f(3.14159) { } +/// }; +/// @endcode +class CXXBaseOrMemberInitializer { + /// \brief Either the base class name (stored as a TypeSourceInfo*) or the + /// field being initialized. + llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember; + + /// \brief The source location for the field name. + SourceLocation MemberLocation; + + /// \brief The argument used to initialize the base or member, which may + /// end up constructing an object (when multiple arguments are involved). + Stmt *Init; + + /// \brief Stores either the constructor to call to initialize this base or + /// member (a CXXConstructorDecl pointer), or stores the anonymous union of + /// which the initialized value is a member. + /// + /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's + /// anonymous union data member, this field holds the FieldDecl for the + /// member of the anonymous union being initialized. + /// @code + /// struct X { + /// X() : au_i1(123) {} + /// union { + /// int au_i1; + /// float au_f1; + /// }; + /// }; + /// @endcode + /// In above example, BaseOrMember holds the field decl. for anonymous union + /// and AnonUnionMember holds field decl for au_i1. + FieldDecl *AnonUnionMember; + + /// LParenLoc - Location of the left paren of the ctor-initializer. + SourceLocation LParenLoc; + + /// RParenLoc - Location of the right paren of the ctor-initializer. + SourceLocation RParenLoc; + + /// IsVirtual - If the initializer is a base initializer, this keeps track + /// of whether the base is virtual or not. + bool IsVirtual : 1; + + /// IsWritten - Whether or not the initializer is explicitly written + /// in the sources. + bool IsWritten : 1; + /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this + /// number keeps track of the textual order of this initializer in the + /// 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; + + CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices); + +public: + /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. + explicit + CXXBaseOrMemberInitializer(ASTContext &Context, + TypeSourceInfo *TInfo, bool IsVirtual, + SourceLocation L, + Expr *Init, + SourceLocation R); + + /// CXXBaseOrMemberInitializer - Creates a new member initializer. + explicit + CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R); + + /// \brief Creates a new member initializer that optionally contains + /// array indices used to describe an elementwise initialization. + static CXXBaseOrMemberInitializer *Create(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices); + + /// \brief Destroy the base or member initializer. + void Destroy(ASTContext &Context); + + /// isBaseInitializer - Returns true when this initializer is + /// initializing a base class. + bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } + + /// isMemberInitializer - Returns true when this initializer is + /// initializing a non-static data member. + bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); } + + /// 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; + + /// If this is a base class initializer, returns the type of the base class. + /// Otherwise, returns NULL. + const Type *getBaseClass() const; + Type *getBaseClass(); + + /// 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 { + return BaseOrMember.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() { + if (isMemberInitializer()) + return BaseOrMember.get<FieldDecl*>(); + else + return 0; + } + + SourceLocation getMemberLocation() const { + return MemberLocation; + } + + void setMember(FieldDecl *Member) { + assert(isMemberInitializer()); + BaseOrMember = Member; + } + + /// \brief Determine the source location of the initializer. + SourceLocation getSourceLocation() const; + + /// \brief Determine the source range covering the entire initializer. + SourceRange getSourceRange() const; + + /// isWritten - Returns true if this initializer is explicitly written + /// in the source code. + bool isWritten() const { return IsWritten; } + + /// \brief Return the source position of the initializer, counting from 0. + /// If the initializer was implicit, -1 is returned. + int getSourceOrder() const { + return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1; + } + + /// \brief Set the source order of this initializer. This method can only + /// be called once for each initializer; it cannot be called on an + /// initializer having a positive number of (implicit) array indices. + void setSourceOrder(int pos) { + assert(!IsWritten && + "calling twice setSourceOrder() on the same initializer"); + assert(SourceOrderOrNumArrayIndices == 0 && + "setSourceOrder() used when there are implicit array indices"); + assert(pos >= 0 && + "setSourceOrder() used to make an initializer implicit"); + IsWritten = true; + SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); + } + + FieldDecl *getAnonUnionMember() const { + return AnonUnionMember; + } + void setAnonUnionMember(FieldDecl *anonMember) { + AnonUnionMember = anonMember; + } + + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + /// \brief Determine the number of implicit array indices used while + /// described an array member initialization. + unsigned getNumArrayIndices() const { + return IsWritten ? 0 : SourceOrderOrNumArrayIndices; + } + + /// \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"); + return reinterpret_cast<VarDecl **>(this + 1)[I]; + } + const VarDecl *getArrayIndex(unsigned I) const { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + return reinterpret_cast<const VarDecl * const *>(this + 1)[I]; + } + void setArrayIndex(unsigned I, VarDecl *Index) { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + reinterpret_cast<VarDecl **>(this + 1)[I] = Index; + } + + Expr *getInit() { return static_cast<Expr *>(Init); } +}; + +/// CXXConstructorDecl - Represents a C++ constructor within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// explicit X(int); // represented by a CXXConstructorDecl. +/// }; +/// @endcode +class CXXConstructorDecl : public CXXMethodDecl { + /// IsExplicitSpecified - Whether this constructor declaration has the + /// 'explicit' keyword specified. + bool IsExplicitSpecified : 1; + + /// ImplicitlyDefined - Whether this constructor was implicitly + /// defined by the compiler. When false, the constructor was defined + /// by the user. In C++03, this flag will have the same value as + /// Implicit. In C++0x, however, a constructor that is + /// explicitly defaulted (i.e., defined with " = default") will have + /// @c !Implicit && ImplicitlyDefined. + bool ImplicitlyDefined : 1; + + /// Support for base and member initializers. + /// BaseOrMemberInitializers - The arguments used to initialize the base + /// or member. + CXXBaseOrMemberInitializer **BaseOrMemberInitializers; + unsigned NumBaseOrMemberInitializers; + + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + bool isExplicitSpecified, bool isInline, + bool isImplicitlyDeclared) + : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), + IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), + BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { + setImplicit(isImplicitlyDeclared); + } + virtual void Destroy(ASTContext& C); + +public: + static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); + static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, TypeSourceInfo *TInfo, + bool isExplicit, + bool isInline, bool isImplicitlyDeclared); + + /// 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()) + ->isExplicitSpecified(); + } + + /// isImplicitlyDefined - Whether this constructor was implicitly + /// defined. If false, then this constructor was defined by the + /// user. This operation can only be invoked if the constructor has + /// already been defined. + bool isImplicitlyDefined() const { + assert(isThisDeclarationADefinition() && + "Can only get the implicit-definition flag once the " + "constructor has been defined"); + return ImplicitlyDefined; + } + + /// setImplicitlyDefined - Set whether this constructor was + /// implicitly defined or not. + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && + "Can only set the implicit-definition flag once the constructor " + "has been defined"); + ImplicitlyDefined = ID; + } + + /// init_iterator - Iterates through the member/base initializer list. + typedef CXXBaseOrMemberInitializer **init_iterator; + + /// init_const_iterator - Iterates through the memberbase initializer list. + typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + + /// init_begin() - Retrieve an iterator to the first initializer. + init_iterator init_begin() { return BaseOrMemberInitializers; } + /// begin() - Retrieve an iterator to the first initializer. + init_const_iterator init_begin() const { return BaseOrMemberInitializers; } + + /// init_end() - Retrieve an iterator past the last initializer. + init_iterator init_end() { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + } + /// end() - Retrieve an iterator past the last initializer. + init_const_iterator init_end() const { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + } + + /// getNumArgs - Determine the number of arguments used to + /// initialize the member or base. + unsigned getNumBaseOrMemberInitializers() const { + return NumBaseOrMemberInitializers; + } + + void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) { + NumBaseOrMemberInitializers = numBaseOrMemberInitializers; + } + + void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) { + BaseOrMemberInitializers = initializers; + } + /// isDefaultConstructor - Whether this constructor is a default + /// constructor (C++ [class.ctor]p5), which can be used to + /// default-initialize a class of this type. + bool isDefaultConstructor() const; + + /// isCopyConstructor - Whether this constructor is a copy + /// constructor (C++ [class.copy]p2, which can be used to copy the + /// class. @p TypeQuals will be set to the qualifiers on the + /// argument type. For example, @p TypeQuals would be set to @c + /// QualType::Const for the following copy constructor: + /// + /// @code + /// class X { + /// public: + /// X(const X&); + /// }; + /// @endcode + bool isCopyConstructor(unsigned &TypeQuals) const; + + /// isCopyConstructor - Whether this constructor is a copy + /// constructor (C++ [class.copy]p2, which can be used to copy the + /// class. + bool isCopyConstructor() const { + unsigned TypeQuals = 0; + return isCopyConstructor(TypeQuals); + } + + /// isConvertingConstructor - Whether this constructor is a + /// converting constructor (C++ [class.conv.ctor]), which can be + /// used for user-defined conversions. + bool isConvertingConstructor(bool AllowExplicit) const; + + /// \brief Determine whether this is a member template specialization that + /// looks like a copy constructor. Such constructors are never used to copy + /// an object. + bool isCopyConstructorLikeSpecialization() const; + + // 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; } +}; + +/// CXXDestructorDecl - Represents a C++ destructor within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// ~X(); // represented by a CXXDestructorDecl. +/// }; +/// @endcode +class CXXDestructorDecl : public CXXMethodDecl { + /// 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 + /// Implicit. In C++0x, however, a destructor that is + /// explicitly defaulted (i.e., defined with " = default") will have + /// @c !Implicit && ImplicitlyDefined. + bool ImplicitlyDefined : 1; + + FunctionDecl *OperatorDelete; + + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, + bool isInline, bool isImplicitlyDeclared) + : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, + FunctionDecl::None, isInline), + ImplicitlyDefined(false), OperatorDelete(0) { + setImplicit(isImplicitlyDeclared); + } + +public: + static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); + static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, bool isInline, + bool isImplicitlyDeclared); + + /// isImplicitlyDefined - Whether this destructor was implicitly + /// defined. If false, then this destructor was defined by the + /// user. This operation can only be invoked if the destructor has + /// already been defined. + bool isImplicitlyDefined() const { + assert(isThisDeclarationADefinition() && + "Can only get the implicit-definition flag once the destructor has been defined"); + return ImplicitlyDefined; + } + + /// setImplicitlyDefined - Set whether this destructor was + /// implicitly defined or not. + void setImplicitlyDefined(bool ID) { + assert(isThisDeclarationADefinition() && + "Can only set the implicit-definition flag once the destructor has been defined"); + ImplicitlyDefined = ID; + } + + void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; } + const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + + // Implement isa/cast/dyncast/etc. + 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; } +}; + +/// CXXConversionDecl - Represents a C++ conversion function within a +/// class. For example: +/// +/// @code +/// class X { +/// public: +/// operator bool(); +/// }; +/// @endcode +class CXXConversionDecl : public CXXMethodDecl { + /// 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; + + CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + bool isInline, bool isExplicitSpecified) + : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), + IsExplicitSpecified(isExplicitSpecified) { } + +public: + static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); + static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation L, DeclarationName N, + QualType T, TypeSourceInfo *TInfo, + bool isInline, bool isExplicit); + + /// 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; } + + /// isExplicit - Whether this is an explicit conversion operator + /// (C++0x only). Explicit conversion operators are only considered + /// when the user has explicitly written a cast. + bool isExplicit() const { + return cast<CXXConversionDecl>(getFirstDeclaration()) + ->isExplicitSpecified(); + } + + /// getConversionType - Returns the type that this conversion + /// function is converting to. + QualType getConversionType() const { + return getType()->getAs<FunctionType>()->getResultType(); + } + + // 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; } +}; + +/// LinkageSpecDecl - This represents a linkage specification. For example: +/// extern "C" void foo(); +/// +class LinkageSpecDecl : public Decl, public DeclContext { +public: + /// LanguageIDs - Used to represent the language in a linkage + /// specification. The values are part of the serialization abi for + /// ASTs and cannot be changed without altering that abi. To help + /// ensure a stable abi for this, we choose the DW_LANG_ encodings + /// from the dwarf standard. + enum LanguageIDs { + lang_c = /* DW_LANG_C */ 0x0002, + lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 + }; +private: + /// Language - The language for this linkage specification. + LanguageIDs Language; + + /// HadBraces - Whether this linkage specification had curly braces or not. + bool HadBraces : 1; + + LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, + bool Braces) + : Decl(LinkageSpec, DC, L), + DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } + +public: + static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, LanguageIDs Lang, + bool Braces); + + /// \brief Return the language specified by this linkage specification. + LanguageIDs getLanguage() const { return Language; } + + /// \brief Set the language specified by this linkage specification. + void setLanguage(LanguageIDs L) { Language = L; } + + /// \brief Determines whether this linkage specification had braces in + /// its syntactic form. + bool hasBraces() const { return HadBraces; } + + /// \brief Set whether this linkage specification has braces in its + /// syntactic form. + void setHasBraces(bool B) { HadBraces = B; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const LinkageSpecDecl *D) { return true; } + static bool classofKind(Kind K) { return K == LinkageSpec; } + static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { + return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D)); + } + static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// UsingDirectiveDecl - Represents C++ using-directive. For example: +/// +/// using namespace std; +/// +// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide +// artificial name, for all using-directives in order to store +// them in DeclContext effectively. +class UsingDirectiveDecl : public NamedDecl { + + /// SourceLocation - Location of 'namespace' token. + SourceLocation NamespaceLoc; + + /// \brief The source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that precedes the namespace + /// name, if any. + NestedNameSpecifier *Qualifier; + + /// IdentLoc - Location of nominated namespace-name identifier. + // FIXME: We don't store location of scope specifier. + SourceLocation IdentLoc; + + /// NominatedNamespace - Namespace nominated by using-directive. + NamedDecl *NominatedNamespace; + + /// Enclosing context containing both using-directive and nominated + /// namespace. + DeclContext *CommonAncestor; + + /// getUsingDirectiveName - Returns special DeclarationName used by + /// using-directives. This is only used by DeclContext for storing + /// UsingDirectiveDecls in its lookup structure. + static DeclarationName getName() { + return DeclarationName::getUsingDirectiveName(); + } + + UsingDirectiveDecl(DeclContext *DC, SourceLocation L, + SourceLocation NamespcLoc, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamedDecl *Nominated, + DeclContext *CommonAncestor) + : NamedDecl(Decl::UsingDirective, DC, L, getName()), + NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), + Qualifier(Qualifier), IdentLoc(IdentLoc), + NominatedNamespace(Nominated), + CommonAncestor(CommonAncestor) { + } + +public: + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the namespace name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Set the source range of the nested-name-specifier that + /// qualifies the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Set the nested-name-specifier that qualifes the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + + NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } + const NamedDecl *getNominatedNamespaceAsWritten() const { + return NominatedNamespace; + } + + /// getNominatedNamespace - Returns namespace nominated by using-directive. + NamespaceDecl *getNominatedNamespace(); + + const NamespaceDecl *getNominatedNamespace() const { + return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); + } + + /// setNominatedNamespace - Set the namespace nominataed by the + /// using-directive. + void setNominatedNamespace(NamedDecl* NS); + + /// \brief Returns the common ancestor context of this using-directive and + /// its nominated namespace. + DeclContext *getCommonAncestor() { return CommonAncestor; } + const DeclContext *getCommonAncestor() const { return CommonAncestor; } + + /// \brief Set the common ancestor context of this using-directive and its + /// nominated namespace. + void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; } + + // FIXME: Could omit 'Key' in name. + /// getNamespaceKeyLocation - Returns location of namespace keyword. + SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } + + /// setNamespaceKeyLocation - Set the the location of the namespacekeyword. + void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; } + + /// getIdentLocation - Returns location of identifier. + SourceLocation getIdentLocation() const { return IdentLoc; } + + /// setIdentLocation - set the location of the identifier. + void setIdentLocation(SourceLocation L) { IdentLoc = L; } + + static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + SourceLocation NamespaceLoc, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamedDecl *Nominated, + DeclContext *CommonAncestor); + + 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 == Decl::UsingDirective; } + + // Friend for getUsingDirectiveName. + friend class DeclContext; +}; + +/// NamespaceAliasDecl - Represents a C++ namespace alias. For example: +/// +/// @code +/// namespace Foo = Bar; +/// @endcode +class NamespaceAliasDecl : public NamedDecl { + SourceLocation AliasLoc; + + /// \brief The source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that precedes the namespace + /// name, if any. + NestedNameSpecifier *Qualifier; + + /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. + SourceLocation IdentLoc; + + /// Namespace - The Decl that this alias points to. Can either be a + /// NamespaceDecl or a NamespaceAliasDecl. + NamedDecl *Namespace; + + NamespaceAliasDecl(DeclContext *DC, SourceLocation L, + SourceLocation AliasLoc, IdentifierInfo *Alias, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, NamedDecl *Namespace) + : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), + QualifierRange(QualifierRange), Qualifier(Qualifier), + IdentLoc(IdentLoc), Namespace(Namespace) { } + +public: + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifiers the namespace name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Set the source range of the nested-name-specifier that qualifies + /// the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Set the nested-name-specifier that qualifies the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + + /// \brief Retrieve the namespace declaration aliased by this directive. + NamespaceDecl *getNamespace() { + if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) + return AD->getNamespace(); + + return cast<NamespaceDecl>(Namespace); + } + + const NamespaceDecl *getNamespace() const { + return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); + } + + /// Returns the location of the alias name, i.e. 'foo' in + /// "namespace foo = ns::bar;". + SourceLocation getAliasLoc() const { return AliasLoc; } + + /// Set the location o;f the alias name, e.e., 'foo' in + /// "namespace foo = ns::bar;". + void setAliasLoc(SourceLocation L) { AliasLoc = L; } + + /// Returns the location of the 'namespace' keyword. + SourceLocation getNamespaceLoc() const { return getLocation(); } + + /// Returns the location of the identifier in the named namespace. + SourceLocation getTargetNameLoc() const { return IdentLoc; } + + /// Set the location of the identifier in the named namespace. + void setTargetNameLoc(SourceLocation L) { IdentLoc = L; } + + /// \brief Retrieve the namespace that this alias refers to, which + /// may either be a NamespaceDecl or a NamespaceAliasDecl. + NamedDecl *getAliasedNamespace() const { return Namespace; } + + /// \brief Set the namespace or namespace alias pointed to by this + /// alias decl. + void setAliasedNamespace(NamedDecl *ND) { + assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) && + "expecting namespace or namespace alias decl"); + Namespace = ND; + } + + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, SourceLocation AliasLoc, + IdentifierInfo *Alias, + SourceRange QualifierRange, + NestedNameSpecifier *Qualifier, + SourceLocation IdentLoc, + NamedDecl *Namespace); + + 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 == Decl::NamespaceAlias; } +}; + +/// UsingShadowDecl - Represents a shadow declaration introduced into +/// a scope by a (resolved) using declaration. For example, +/// +/// namespace A { +/// void foo(); +/// } +/// namespace B { +/// using A::foo(); // <- a UsingDecl +/// // Also creates a UsingShadowDecl for A::foo in B +/// } +/// +class UsingShadowDecl : public NamedDecl { + /// The referenced declaration. + NamedDecl *Underlying; + + /// The using declaration which introduced this decl. + UsingDecl *Using; + + UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) + : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()), + Underlying(Target), Using(Using) { + IdentifierNamespace = Target->getIdentifierNamespace(); + setImplicit(); + } + +public: + static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) { + return new (C) UsingShadowDecl(DC, Loc, Using, Target); + } + + /// \brief Gets the underlying declaration which has been brought into the + /// local scope. + NamedDecl *getTargetDecl() const { return Underlying; } + + /// \brief Sets the underlying declaration which has been brought into the + /// local scope. + void setTargetDecl(NamedDecl* ND) { Underlying = ND; } + + /// \brief Gets the using declaration to which this declaration is tied. + UsingDecl *getUsingDecl() const { return Using; } + + /// \brief Sets the using declaration that introduces this target + /// declaration. + void setUsingDecl(UsingDecl* UD) { Using = UD; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const UsingShadowDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UsingShadow; } +}; + +/// UsingDecl - Represents a C++ using-declaration. For example: +/// using someNameSpace::someIdentifier; +class UsingDecl : public NamedDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange NestedNameRange; + + /// \brief The source location of the "using" location itself. + SourceLocation UsingLocation; + + /// \brief Target nested name specifier. + NestedNameSpecifier* TargetNestedName; + + /// \brief The collection of shadow declarations associated with + /// this using declaration. This set can change as a class is + /// processed. + llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows; + + // \brief Has 'typename' keyword. + bool IsTypeName; + + UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, + SourceLocation UL, NestedNameSpecifier* TargetNNS, + DeclarationName Name, bool IsTypeNameArg) + : NamedDecl(Decl::Using, DC, L, Name), + NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), + IsTypeName(IsTypeNameArg) { + } + +public: + // FIXME: Should be const? + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getNestedNameRange() { return NestedNameRange; } + + /// \brief Set the source range of the nested-name-specifier. + void setNestedNameRange(SourceRange R) { NestedNameRange = R; } + + // FIXME; Should be const? + // FIXME: Naming is inconsistent with other get*Loc functions. + /// \brief Returns the source location of the "using" keyword. + SourceLocation getUsingLocation() { return UsingLocation; } + + /// \brief Set the source location of the 'using' keyword. + void setUsingLocation(SourceLocation L) { UsingLocation = L; } + + + /// \brief Get the target nested name declaration. + NestedNameSpecifier* getTargetNestedNameDecl() { + return TargetNestedName; + } + + /// \brief Set the target nested name declaration. + void setTargetNestedNameDecl(NestedNameSpecifier *NNS) { + TargetNestedName = NNS; + } + + /// \brief Return true if the using declaration has 'typename'. + bool isTypeName() const { return IsTypeName; } + + /// \brief Sets whether the using declaration has 'typename'. + void setTypeName(bool TN) { IsTypeName = TN; } + + typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator; + shadow_iterator shadow_begin() const { return Shadows.begin(); } + shadow_iterator shadow_end() const { return Shadows.end(); } + + void addShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.insert(S)) { + assert(false && "declaration already in set"); + } + } + void removeShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.erase(S)) { + assert(false && "declaration not in set"); + } + } + + /// \brief Return the number of shadowed declarations associated with this + /// using declaration. + unsigned getNumShadowDecls() const { + return Shadows.size(); + } + + static UsingDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, + NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const UsingDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::Using; } +}; + +/// UnresolvedUsingValueDecl - Represents a dependent using +/// declaration which was not marked with 'typename'. Unlike +/// non-dependent using declarations, these *only* bring through +/// non-types; otherwise they would break two-phase lookup. +/// +/// template <class T> class A : public Base<T> { +/// using Base<T>::foo; +/// }; +class UnresolvedUsingValueDecl : public ValueDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange TargetNestedNameRange; + + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; + + NestedNameSpecifier *TargetNestedNameSpecifier; + + UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, + SourceLocation UsingLoc, SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName) + : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TargetNestedNameSpecifier(TargetNNS) + { } + +public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + + static UnresolvedUsingValueDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const UnresolvedUsingValueDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingValue; } +}; + +/// UnresolvedUsingTypenameDecl - Represents a dependent using +/// declaration which was marked with 'typename'. +/// +/// template <class T> class A : public Base<T> { +/// using typename Base<T>::foo; +/// }; +/// +/// The type associated with a unresolved using typename decl is +/// currently always a typename type. +class UnresolvedUsingTypenameDecl : public TypeDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange TargetNestedNameRange; + + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; + + /// \brief The source location of the 'typename' keyword + SourceLocation TypenameLocation; + + NestedNameSpecifier *TargetNestedNameSpecifier; + + UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, IdentifierInfo *TargetName) + : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) + { } + +public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + + /// \brief Returns the source location of the 'typename' keyword. + SourceLocation getTypenameLoc() const { return TypenameLocation; } + + /// \brief Set the source location of the 'typename' keyword. + void setTypenameLoc(SourceLocation L) { TypenameLocation = L; } + + static UnresolvedUsingTypenameDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); + + 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 == Decl::UnresolvedUsingTypename; } +}; + +/// StaticAssertDecl - Represents a C++0x static_assert declaration. +class StaticAssertDecl : public Decl { + Expr *AssertExpr; + StringLiteral *Message; + + StaticAssertDecl(DeclContext *DC, SourceLocation L, + Expr *assertexpr, StringLiteral *message) + : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { } + +public: + static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, Expr *AssertExpr, + StringLiteral *Message); + + Expr *getAssertExpr() { return AssertExpr; } + const Expr *getAssertExpr() const { return AssertExpr; } + + StringLiteral *getMessage() { return Message; } + const StringLiteral *getMessage() const { return Message; } + + virtual ~StaticAssertDecl(); + virtual void Destroy(ASTContext& C); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(StaticAssertDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::StaticAssert; } +}; + +/// Insertion operator for diagnostics. This allows sending AccessSpecifier's +/// into a diagnostic with <<. +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + AccessSpecifier AS); + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h new file mode 100644 index 0000000..9602b67 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h @@ -0,0 +1,289 @@ +//===-- DeclContextInternals.h - DeclContext Representation -----*- 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 data structures used in the implementation +// of DeclContext. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H +#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclCXX.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include <algorithm> + +namespace clang { + +class DependentDiagnostic; + +/// StoredDeclsList - This is an array of decls optimized a common case of only +/// containing one entry. +struct StoredDeclsList { + /// The kind of data encoded in this list. + enum DataKind { + /// \brief The data is a NamedDecl*. + DK_Decl = 0, + /// \brief The data is a declaration ID (an unsigned value), + /// shifted left by 2 bits. + DK_DeclID = 1, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declarations. + DK_Decl_Vector = 2, + /// \brief The data is a pointer to a vector (of type VectorTy) + /// that contains declaration ID. + DK_ID_Vector = 3 + }; + + /// VectorTy - When in vector form, this is what the Data pointer points to. + typedef llvm::SmallVector<uintptr_t, 4> VectorTy; + + /// \brief The stored data, which will be either a declaration ID, a + /// pointer to a NamedDecl, or a pointer to a vector. + uintptr_t Data; + +public: + StoredDeclsList() : Data(0) {} + + StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); + } + } + + ~StoredDeclsList() { + // If this is a vector-form, free the vector. + if (VectorTy *Vector = getAsVector()) + delete Vector; + } + + StoredDeclsList &operator=(const StoredDeclsList &RHS) { + if (VectorTy *Vector = getAsVector()) + delete Vector; + Data = RHS.Data; + if (VectorTy *RHSVec = RHS.getAsVector()) { + VectorTy *New = new VectorTy(*RHSVec); + Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); + } + return *this; + } + + bool isNull() const { return (Data & ~0x03) == 0; } + + NamedDecl *getAsDecl() const { + if ((Data & 0x03) != DK_Decl) + return 0; + + return reinterpret_cast<NamedDecl *>(Data & ~0x03); + } + + VectorTy *getAsVector() const { + if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) + return 0; + + return reinterpret_cast<VectorTy *>(Data & ~0x03); + } + + void setOnlyValue(NamedDecl *ND) { + assert(!getAsVector() && "Not inline"); + Data = reinterpret_cast<uintptr_t>(ND); + } + + void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { + if (Vec.size() > 1) { + VectorTy *Vector = getAsVector(); + if (!Vector) { + Vector = new VectorTy; + Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector; + } + + Vector->resize(Vec.size()); + std::copy(Vec.begin(), Vec.end(), Vector->begin()); + return; + } + + if (VectorTy *Vector = getAsVector()) + delete Vector; + + if (Vec.empty()) + Data = 0; + else + Data = (Vec[0] << 2) | DK_DeclID; + } + + /// \brief Force the stored declarations list to contain actual + /// declarations. + /// + /// This routine will resolve any declaration IDs for declarations + /// that may not yet have been loaded from external storage. + void materializeDecls(ASTContext &Context); + + bool hasDeclarationIDs() const { + DataKind DK = (DataKind)(Data & 0x03); + return DK == DK_DeclID || DK == DK_ID_Vector; + } + + void remove(NamedDecl *D) { + assert(!isNull() && "removing from empty list"); + if (NamedDecl *Singleton = getAsDecl()) { + assert(Singleton == D && "list is different singleton"); + (void)Singleton; + Data = 0; + return; + } + + VectorTy &Vec = *getAsVector(); + VectorTy::iterator I = std::find(Vec.begin(), Vec.end(), + reinterpret_cast<uintptr_t>(D)); + assert(I != Vec.end() && "list does not contain decl"); + Vec.erase(I); + + assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D)) + == Vec.end() && "list still contains decl"); + } + + /// getLookupResult - Return an array of all the decls that this list + /// represents. + DeclContext::lookup_result getLookupResult(ASTContext &Context) { + if (isNull()) + return DeclContext::lookup_result(DeclContext::lookup_iterator(0), + DeclContext::lookup_iterator(0)); + + if (hasDeclarationIDs()) + materializeDecls(Context); + + // If we have a single NamedDecl, return it. + if (getAsDecl()) { + assert(!isNull() && "Empty list isn't allowed"); + + // Data is a raw pointer to a NamedDecl*, return it. + void *Ptr = &Data; + return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); + } + + assert(getAsVector() && "Must have a vector at this point"); + VectorTy &Vector = *getAsVector(); + + // Otherwise, we have a range result. + return DeclContext::lookup_result((NamedDecl **)&Vector[0], + (NamedDecl **)&Vector[0]+Vector.size()); + } + + /// HandleRedeclaration - If this is a redeclaration of an existing decl, + /// replace the old one with D and return true. Otherwise return false. + bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { + if (hasDeclarationIDs()) + materializeDecls(Context); + + // Most decls only have one entry in their list, special case it. + if (NamedDecl *OldD = getAsDecl()) { + if (!D->declarationReplaces(OldD)) + return false; + setOnlyValue(D); + return true; + } + + // Determine if this declaration is actually a redeclaration. + VectorTy &Vec = *getAsVector(); + for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); + OD != ODEnd; ++OD) { + NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); + if (D->declarationReplaces(OldD)) { + *OD = reinterpret_cast<uintptr_t>(D); + return true; + } + } + + return false; + } + + /// AddSubsequentDecl - This is called on the second and later decl when it is + /// not a redeclaration to merge it into the appropriate place in our list. + /// + void AddSubsequentDecl(NamedDecl *D) { + assert(!hasDeclarationIDs() && "Must materialize before adding decls"); + + // If this is the second decl added to the list, convert this to vector + // form. + if (NamedDecl *OldD = getAsDecl()) { + VectorTy *VT = new VectorTy(); + VT->push_back(reinterpret_cast<uintptr_t>(OldD)); + Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; + } + + VectorTy &Vec = *getAsVector(); + + // Using directives end up in a special entry which contains only + // other using directives, so all this logic is wasted for them. + // But avoiding the logic wastes time in the far-more-common case + // that we're *not* adding a new using directive. + + // Tag declarations always go at the end of the list so that an + // iterator which points at the first tag will start a span of + // decls that only contains tags. + if (D->hasTagIdentifierNamespace()) + Vec.push_back(reinterpret_cast<uintptr_t>(D)); + + // Resolved using declarations go at the front of the list so that + // they won't show up in other lookup results. Unresolved using + // declarations (which are always in IDNS_Using | IDNS_Ordinary) + // follow that so that the using declarations will be contiguous. + else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { + VectorTy::iterator I = Vec.begin(); + if (D->getIdentifierNamespace() != Decl::IDNS_Using) { + while (I != Vec.end() && + reinterpret_cast<NamedDecl *>(*I) + ->getIdentifierNamespace() == Decl::IDNS_Using) + ++I; + } + Vec.insert(I, reinterpret_cast<uintptr_t>(D)); + + // All other declarations go at the end of the list, but before any + // tag declarations. But we can be clever about tag declarations + // because there can only ever be one in a scope. + } else if (reinterpret_cast<NamedDecl *>(Vec.back()) + ->hasTagIdentifierNamespace()) { + uintptr_t TagD = Vec.back(); + Vec.back() = reinterpret_cast<uintptr_t>(D); + Vec.push_back(TagD); + } else + Vec.push_back(reinterpret_cast<uintptr_t>(D)); + } +}; + +class StoredDeclsMap + : public llvm::DenseMap<DeclarationName, StoredDeclsList> { + +public: + static void DestroyAll(StoredDeclsMap *Map, bool Dependent); + +private: + friend class ASTContext; // walks the chain deleting these + friend class DeclContext; + llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; +}; + +class DependentStoredDeclsMap : public StoredDeclsMap { +public: + DependentStoredDeclsMap() : FirstDiagnostic(0) {} + +private: + friend class DependentDiagnostic; + friend class DeclContext; // iterates over diagnostics + + DependentDiagnostic *FirstDiagnostic; +}; + +} // 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 new file mode 100644 index 0000000..a20625d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h @@ -0,0 +1,159 @@ +//===-- DeclFriend.h - Classes for C++ friend declarations -*- 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 section of the AST representing C++ friend +// declarations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLFRIEND_H +#define LLVM_CLANG_AST_DECLFRIEND_H + +#include "clang/AST/DeclCXX.h" + +namespace clang { + +/// FriendDecl - Represents the declaration of a friend entity, +/// which can be a function, a type, or a templated function or type. +// For example: +/// +/// @code +/// template <typename T> class A { +/// friend int foo(T); +/// friend class B; +/// friend T; // only in C++0x +/// template <typename U> friend class C; +/// template <typename U> friend A& operator+=(A&, const U&) { ... } +/// }; +/// @endcode +/// +/// The semantic context of a friend decl is its declaring class. +class FriendDecl : public Decl { +public: + typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; + +private: + // The declaration that's a friend of this class. + FriendUnion Friend; + + // A pointer to the next friend in the sequence. + FriendDecl *NextFriend; + + // Location of the 'friend' specifier. + SourceLocation FriendLoc; + + friend class CXXRecordDecl::friend_iterator; + friend class CXXRecordDecl; + + FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, + SourceLocation FriendL) + : Decl(Decl::Friend, DC, L), + Friend(Friend), + NextFriend(0), + FriendLoc(FriendL) { + } + +public: + static FriendDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, FriendUnion Friend_, + SourceLocation FriendL); + + /// If this friend declaration names an (untemplated but + /// possibly dependent) type, return the type; otherwise + /// return null. This is used only for C++0x's unelaborated + /// friend type declarations. + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast<TypeSourceInfo*>(); + } + + /// If this friend declaration doesn't name an unelaborated + /// type, return the inner declaration. + NamedDecl *getFriendDecl() const { + return Friend.dyn_cast<NamedDecl*>(); + } + + /// Retrieves the location of the 'friend' keyword. + SourceLocation getFriendLoc() const { + return FriendLoc; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FriendDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Decl::Friend; } +}; + +/// An iterator over the friend declarations of a class. +class CXXRecordDecl::friend_iterator { + FriendDecl *Ptr; + + friend class CXXRecordDecl; + explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {} +public: + friend_iterator() {} + + typedef FriendDecl *value_type; + typedef FriendDecl *reference; + typedef FriendDecl *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + reference operator*() const { return Ptr; } + + friend_iterator &operator++() { + assert(Ptr && "attempt to increment past end of friend list"); + Ptr = Ptr->NextFriend; + return *this; + } + + friend_iterator operator++(int) { + friend_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const friend_iterator &Other) const { + return Ptr == Other.Ptr; + } + + bool operator!=(const friend_iterator &Other) const { + return Ptr != Other.Ptr; + } + + friend_iterator &operator+=(difference_type N) { + assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator"); + while (N--) + ++*this; + return *this; + } + + friend_iterator operator+(difference_type N) const { + friend_iterator tmp = *this; + tmp += N; + return tmp; + } +}; + +inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { + return friend_iterator(data().FirstFriend); +} + +inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { + return friend_iterator(0); +} + +inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { + assert(FD->NextFriend == 0 && "friend already has next friend?"); + FD->NextFriend = data().FirstFriend; + data().FirstFriend = FD; +} + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h new file mode 100644 index 0000000..e1fae8f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h @@ -0,0 +1,152 @@ +//===--- DeclGroup.h - Classes for representing groups of Decls -*- 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 DeclGroup, DeclGroupRef, and OwningDeclGroup classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLGROUP_H +#define LLVM_CLANG_AST_DECLGROUP_H + +#include "llvm/System/DataTypes.h" +#include <cassert> + +namespace clang { + +class ASTContext; +class Decl; +class DeclGroup; +class DeclGroupIterator; + +class DeclGroup { + // FIXME: Include a TypeSpecifier object. + unsigned NumDecls; + +private: + DeclGroup() : NumDecls(0) {} + DeclGroup(unsigned numdecls, Decl** decls); + +public: + static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); + void Destroy(ASTContext& C); + + unsigned size() const { return NumDecls; } + + Decl*& operator[](unsigned i) { + assert (i < NumDecls && "Out-of-bounds access."); + return *((Decl**) (this+1)); + } + + Decl* const& operator[](unsigned i) const { + assert (i < NumDecls && "Out-of-bounds access."); + return *((Decl* const*) (this+1)); + } +}; + +class DeclGroupRef { + // Note this is not a PointerIntPair because we need the address of the + // non-group case to be valid as a Decl** for iteration. + enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; + Decl* D; + + Kind getKind() const { + return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); + } + +public: + DeclGroupRef() : D(0) {} + + explicit DeclGroupRef(Decl* d) : D(d) {} + explicit DeclGroupRef(DeclGroup* dg) + : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} + + static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { + if (NumDecls == 0) + return DeclGroupRef(); + if (NumDecls == 1) + return DeclGroupRef(Decls[0]); + return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); + } + + typedef Decl** iterator; + typedef Decl* const * const_iterator; + + bool isNull() const { return D == 0; } + bool isSingleDecl() const { return getKind() == SingleDeclKind; } + bool isDeclGroup() const { return getKind() == DeclGroupKind; } + + Decl *getSingleDecl() { + assert(isSingleDecl() && "Isn't a declgroup"); + return D; + } + const Decl *getSingleDecl() const { + return const_cast<DeclGroupRef*>(this)->getSingleDecl(); + } + + DeclGroup &getDeclGroup() { + assert(isDeclGroup() && "Isn't a declgroup"); + return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); + } + const DeclGroup &getDeclGroup() const { + return const_cast<DeclGroupRef*>(this)->getDeclGroup(); + } + + iterator begin() { + if (isSingleDecl()) + return D ? &D : 0; + return &getDeclGroup()[0]; + } + + iterator end() { + if (isSingleDecl()) + return D ? &D+1 : 0; + DeclGroup &G = getDeclGroup(); + return &G[0] + G.size(); + } + + const_iterator begin() const { + if (isSingleDecl()) + return D ? &D : 0; + return &getDeclGroup()[0]; + } + + const_iterator end() const { + if (isSingleDecl()) + return D ? &D+1 : 0; + const DeclGroup &G = getDeclGroup(); + return &G[0] + G.size(); + } + + void *getAsOpaquePtr() const { return D; } + static DeclGroupRef getFromOpaquePtr(void *Ptr) { + DeclGroupRef X; + X.D = static_cast<Decl*>(Ptr); + return X; + } +}; + +} // end clang namespace + +namespace llvm { + // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. + template <typename T> + class PointerLikeTypeTraits; + template <> + class PointerLikeTypeTraits<clang::DeclGroupRef> { + public: + static inline void *getAsVoidPointer(clang::DeclGroupRef P) { + return P.getAsOpaquePtr(); + } + static inline clang::DeclGroupRef getFromVoidPointer(void *P) { + return clang::DeclGroupRef::getFromOpaquePtr(P); + } + enum { NumLowBitsAvailable = 0 }; + }; +} +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclNodes.def b/contrib/llvm/tools/clang/include/clang/AST/DeclNodes.def new file mode 100644 index 0000000..5b03ff8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclNodes.def @@ -0,0 +1,165 @@ +//===-- DeclNodes.def - Metadata about Decl AST nodes -----------*- 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 declaration nodes within the AST. The +// description of the declaration nodes uses six macros: +// +// DECL(Derived, Base) describes a normal declaration type Derived +// and specifies its base class. Note that Derived should not have +// the Decl suffix on it, while Base should. +// +// LAST_DECL(Derived, Base) is like DECL, but is used for the last +// declaration in the list. +// +// ABSTRACT_DECL(Derived, Base) describes an abstract class that is +// used to specify a classification of declarations. For example, +// TagDecl is an abstract class used to describe the various kinds of +// "tag" declarations (unions, structs, classes, enums). +// +// DECL_CONTEXT(Decl) specifies that Decl is a kind of declaration +// that is also a DeclContext. +// +// LAST_DECL_CONTEXT(Decl) is like DECL_CONTEXT, but is used for the +// last declaration context. +// +// DECL_RANGE(CommonBase, Start, End) specifies a range of +// declaration values that have a common (potentially indirect) base +// class. +// +// LAST_DECL_RANGE(CommonBase, Start, End) is like DECL_RANGE, but is +// used for the last declaration range. +// +// Note that, due to the use of ranges, the order of the these +// declarations is significant. A declaration should be listed under +// its base class. +// ===----------------------------------------------------------------------===// + +#ifndef DECL +# define DECL(Derived, Base) +#endif + +#ifndef LAST_DECL +# define LAST_DECL(Derived, Base) DECL(Derived, Base) +#endif + +#ifndef ABSTRACT_DECL +# define ABSTRACT_DECL(Derived, Base) +#endif + +#ifndef DECL_CONTEXT +# define DECL_CONTEXT(Decl) +#endif + +#ifndef DECL_CONTEXT_BASE +# define DECL_CONTEXT_BASE(Decl) DECL_CONTEXT(Decl) +#endif + +#ifndef LAST_DECL_CONTEXT +# define LAST_DECL_CONTEXT(Decl) DECL_CONTEXT(Decl) +#endif + +#ifndef DECL_RANGE +# define DECL_RANGE(CommonBase, Start, End) +#endif + +#ifndef LAST_DECL_RANGE +# define LAST_DECL_RANGE(CommonBase, Start, End) \ + DECL_RANGE(CommonBase, Start, End) +#endif + +DECL(TranslationUnit, Decl) +ABSTRACT_DECL(Named, Decl) + DECL(Namespace, NamedDecl) + DECL(UsingDirective, NamedDecl) + DECL(NamespaceAlias, NamedDecl) + ABSTRACT_DECL(Type, NamedDecl) + DECL(Typedef, TypeDecl) + DECL(UnresolvedUsingTypename, TypeDecl) + ABSTRACT_DECL(Tag, TypeDecl) + DECL(Enum, TagDecl) + DECL(Record, TagDecl) + DECL(CXXRecord, RecordDecl) + DECL(ClassTemplateSpecialization, CXXRecordDecl) + DECL(ClassTemplatePartialSpecialization, + ClassTemplateSpecializationDecl) + DECL(TemplateTypeParm, TypeDecl) + ABSTRACT_DECL(Value, NamedDecl) + DECL(EnumConstant, ValueDecl) + DECL(UnresolvedUsingValue, ValueDecl) + ABSTRACT_DECL(Declarator, ValueDecl) + DECL(Function, DeclaratorDecl) + DECL(CXXMethod, FunctionDecl) + DECL(CXXConstructor, CXXMethodDecl) + DECL(CXXDestructor, CXXMethodDecl) + DECL(CXXConversion, CXXMethodDecl) + DECL(Field, DeclaratorDecl) + DECL(ObjCIvar, FieldDecl) + DECL(ObjCAtDefsField, FieldDecl) + DECL(Var, DeclaratorDecl) + DECL(ImplicitParam, VarDecl) + DECL(ParmVar, VarDecl) + DECL(NonTypeTemplateParm, VarDecl) + ABSTRACT_DECL(Template, NamedDecl) + DECL(FunctionTemplate, TemplateDecl) + DECL(ClassTemplate, TemplateDecl) + DECL(TemplateTemplateParm, TemplateDecl) + DECL(Using, NamedDecl) + DECL(UsingShadow, NamedDecl) + DECL(ObjCMethod, NamedDecl) + ABSTRACT_DECL(ObjCContainer, NamedDecl) + DECL(ObjCCategory, ObjCContainerDecl) + DECL(ObjCProtocol, ObjCContainerDecl) + DECL(ObjCInterface, ObjCContainerDecl) + ABSTRACT_DECL(ObjCImpl, ObjCContainerDecl) + DECL(ObjCCategoryImpl, ObjCImplDecl) + DECL(ObjCImplementation, ObjCImplDecl) + DECL(ObjCProperty, NamedDecl) + DECL(ObjCCompatibleAlias, NamedDecl) +DECL(LinkageSpec, Decl) +DECL(ObjCPropertyImpl, Decl) +DECL(ObjCForwardProtocol, Decl) +DECL(ObjCClass, Decl) +DECL(FileScopeAsm, Decl) +DECL(Friend, Decl) +DECL(FriendTemplate, Decl) +DECL(StaticAssert, Decl) +LAST_DECL(Block, Decl) + +// Declaration contexts. DECL_CONTEXT_BASE indicates that it has subclasses. +DECL_CONTEXT(TranslationUnit) +DECL_CONTEXT(Namespace) +DECL_CONTEXT(LinkageSpec) +DECL_CONTEXT(ObjCMethod) +DECL_CONTEXT_BASE(Tag) +DECL_CONTEXT_BASE(Function) +DECL_CONTEXT_BASE(ObjCContainer) +LAST_DECL_CONTEXT(Block) + +// Declaration ranges +DECL_RANGE(Named, Namespace, ObjCCompatibleAlias) +DECL_RANGE(ObjCContainer, ObjCCategory, ObjCImplementation) +DECL_RANGE(Field, Field, ObjCAtDefsField) +DECL_RANGE(Type, Typedef, TemplateTypeParm) +DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization) +DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization) +DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm) +DECL_RANGE(Declarator, Function, NonTypeTemplateParm) +DECL_RANGE(Function, Function, CXXConversion) +DECL_RANGE(Template, FunctionTemplate, TemplateTemplateParm) +DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation) +LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm) + +#undef LAST_DECL_RANGE +#undef DECL_RANGE +#undef LAST_DECL_CONTEXT +#undef DECL_CONTEXT_BASE +#undef DECL_CONTEXT +#undef ABSTRACT_DECL +#undef LAST_DECL +#undef DECL diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h new file mode 100644 index 0000000..97d1656 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h @@ -0,0 +1,1489 @@ +//===--- DeclObjC.h - Classes for representing declarations -----*- 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 DeclObjC interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLOBJC_H +#define LLVM_CLANG_AST_DECLOBJC_H + +#include "clang/AST/Decl.h" +#include "llvm/ADT/STLExtras.h" + +namespace clang { +class Expr; +class Stmt; +class FunctionDecl; +class AttributeList; +class RecordDecl; +class ObjCIvarDecl; +class ObjCMethodDecl; +class ObjCProtocolDecl; +class ObjCCategoryDecl; +class ObjCPropertyDecl; +class ObjCPropertyImplDecl; +class CXXBaseOrMemberInitializer; + +class ObjCListBase { + void operator=(const ObjCListBase &); // DO NOT IMPLEMENT + ObjCListBase(const ObjCListBase&); // DO NOT IMPLEMENT +protected: + /// List is an array of pointers to objects that are not owned by this object. + void **List; + unsigned NumElts; + +public: + ObjCListBase() : List(0), NumElts(0) {} + ~ObjCListBase() { + assert(List == 0 && "Destroy should have been called before dtor"); + } + + void Destroy(ASTContext &Ctx); + + unsigned size() const { return NumElts; } + bool empty() const { return NumElts == 0; } + +protected: + void set(void *const* InList, unsigned Elts, ASTContext &Ctx); +}; + + +/// ObjCList - This is a simple template class used to hold various lists of +/// decls etc, which is heavily used by the ObjC front-end. This only use case +/// this supports is setting the list all at once and then reading elements out +/// of it. +template <typename T> +class ObjCList : public ObjCListBase { +public: + void set(T* const* InList, unsigned Elts, ASTContext &Ctx) { + ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx); + } + + typedef T* const * iterator; + iterator begin() const { return (iterator)List; } + iterator end() const { return (iterator)List+NumElts; } + + T* operator[](unsigned Idx) const { + assert(Idx < NumElts && "Invalid access"); + return (T*)List[Idx]; + } +}; + +/// \brief A list of Objective-C protocols, along with the source +/// locations at which they were referenced. +class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> { + SourceLocation *Locations; + + using ObjCList<ObjCProtocolDecl>::set; + +public: + ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { } + + typedef const SourceLocation *loc_iterator; + loc_iterator loc_begin() const { return Locations; } + loc_iterator loc_end() const { return Locations + size(); } + + void set(ObjCProtocolDecl* const* InList, unsigned Elts, + const SourceLocation *Locs, ASTContext &Ctx); + void Destroy(ASTContext &Ctx); +}; + + +/// ObjCMethodDecl - Represents an instance or class method declaration. +/// ObjC methods can be declared within 4 contexts: class interfaces, +/// categories, protocols, and class implementations. While C++ member +/// functions leverage C syntax, Objective-C method syntax is modeled after +/// Smalltalk (using colons to specify argument types/expressions). +/// Here are some brief examples: +/// +/// Setter/getter instance methods: +/// - (void)setMenu:(NSMenu *)menu; +/// - (NSMenu *)menu; +/// +/// Instance method that takes 2 NSView arguments: +/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView; +/// +/// Getter class method: +/// + (NSMenu *)defaultMenu; +/// +/// A selector represents a unique name for a method. The selector names for +/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu. +/// +class ObjCMethodDecl : public NamedDecl, public DeclContext { +public: + enum ImplementationControl { None, Required, Optional }; +private: + /// Bitfields must be first fields in this class so they pack with those + /// declared in class Decl. + /// instance (true) or class (false) method. + bool IsInstance : 1; + bool IsVariadic : 1; + + // Synthesized declaration method for a property setter/getter + bool IsSynthesized : 1; + + // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum + /// @required/@optional + unsigned DeclImplementation : 2; + + // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum + /// in, inout, etc. + unsigned objcDeclQualifier : 6; + + // Number of args separated by ':' in a method declaration. + unsigned NumSelectorArgs; + + // Result type of this method. + QualType MethodDeclType; + + // Type source information for the result type. + TypeSourceInfo *ResultTInfo; + + /// ParamInfo - List of pointers to VarDecls for the formal parameters of this + /// Method. + ObjCList<ParmVarDecl> ParamInfo; + + /// List of attributes for this method declaration. + SourceLocation EndLoc; // the location of the ';' or '}'. + + // The following are only used for method definitions, null otherwise. + // FIXME: space savings opportunity, consider a sub-class. + Stmt *Body; + + /// SelfDecl - Decl for the implicit self parameter. This is lazily + /// constructed by createImplicitParams. + ImplicitParamDecl *SelfDecl; + /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily + /// constructed by createImplicitParams. + ImplicitParamDecl *CmdDecl; + + ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, + Selector SelInfo, QualType T, + TypeSourceInfo *ResultTInfo, + DeclContext *contextDecl, + bool isInstance = true, + bool isVariadic = false, + bool isSynthesized = false, + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0) + : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), + DeclContext(ObjCMethod), + IsInstance(isInstance), IsVariadic(isVariadic), + IsSynthesized(isSynthesized), + DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), + NumSelectorArgs(numSelectorArgs), MethodDeclType(T), + ResultTInfo(ResultTInfo), + EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} + + virtual ~ObjCMethodDecl() {} + + /// \brief A definition will return its interface declaration. + /// An interface declaration will return its definition. + /// Otherwise it will return itself. + virtual ObjCMethodDecl *getNextRedeclaration(); + +public: + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + static ObjCMethodDecl *Create(ASTContext &C, + SourceLocation beginLoc, + SourceLocation endLoc, Selector SelInfo, + QualType T, + TypeSourceInfo *ResultTInfo, + DeclContext *contextDecl, + bool isInstance = true, + bool isVariadic = false, + bool isSynthesized = false, + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0); + + virtual ObjCMethodDecl *getCanonicalDecl(); + const ObjCMethodDecl *getCanonicalDecl() const { + return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl(); + } + + ObjCDeclQualifier getObjCDeclQualifier() const { + return ObjCDeclQualifier(objcDeclQualifier); + } + void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } + + unsigned getNumSelectorArgs() const { return NumSelectorArgs; } + void setNumSelectorArgs(unsigned numSelectorArgs) { + NumSelectorArgs = numSelectorArgs; + } + + // Location information, modeled after the Stmt API. + SourceLocation getLocStart() const { return getLocation(); } + SourceLocation getLocEnd() const { return EndLoc; } + void setEndLoc(SourceLocation Loc) { EndLoc = Loc; } + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), EndLoc); + } + + ObjCInterfaceDecl *getClassInterface(); + const ObjCInterfaceDecl *getClassInterface() const { + return const_cast<ObjCMethodDecl*>(this)->getClassInterface(); + } + + Selector getSelector() const { return getDeclName().getObjCSelector(); } + + QualType getResultType() const { return MethodDeclType; } + void setResultType(QualType T) { MethodDeclType = T; } + + TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; } + void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; } + + // Iterator access to formal parameters. + unsigned param_size() const { return ParamInfo.size(); } + typedef ObjCList<ParmVarDecl>::iterator param_iterator; + param_iterator param_begin() const { return ParamInfo.begin(); } + param_iterator param_end() const { return ParamInfo.end(); } + // This method returns and of the parameters which are part of the selector + // name mangling requirements. + param_iterator sel_param_end() const { + return ParamInfo.begin() + NumSelectorArgs; + } + + void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num, + unsigned numSelectorArgs) { + ParamInfo.set(List, Num, C); + NumSelectorArgs = numSelectorArgs; + } + + // Iterator access to parameter types. + typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; + typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator; + + arg_type_iterator arg_type_begin() const { + return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType)); + } + arg_type_iterator arg_type_end() const { + return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType)); + } + + /// createImplicitParams - Used to lazily create the self and cmd + /// implict parameters. This must be called prior to using getSelfDecl() + /// or getCmdDecl(). The call is ignored if the implicit paramters + /// have already been created. + void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID); + + ImplicitParamDecl * getSelfDecl() const { return SelfDecl; } + void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; } + ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } + void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } + + bool isInstanceMethod() const { return IsInstance; } + void setInstanceMethod(bool isInst) { IsInstance = isInst; } + bool isVariadic() const { return IsVariadic; } + void setVariadic(bool isVar) { IsVariadic = isVar; } + + bool isClassMethod() const { return !IsInstance; } + + bool isSynthesized() const { return IsSynthesized; } + void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } + + // Related to protocols declared in @protocol + void setDeclImplementation(ImplementationControl ic) { + DeclImplementation = ic; + } + ImplementationControl getImplementationControl() const { + return ImplementationControl(DeclImplementation); + } + + virtual Stmt *getBody() const { + return (Stmt*) Body; + } + CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; } + void setBody(Stmt *B) { Body = B; } + + /// \brief Returns whether this specific method is a definition. + bool isThisDeclarationADefinition() const { return Body; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCMethodDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCMethod; } + static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { + return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D)); + } + static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// ObjCMethodList - a linked list of methods with different signatures. +struct ObjCMethodList { + ObjCMethodDecl *Method; + ObjCMethodList *Next; + + ObjCMethodList() { + Method = 0; + Next = 0; + } + ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { + Method = M; + Next = C; + } +}; + +/// ObjCContainerDecl - Represents a container for method declarations. +/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, +/// ObjCProtocolDecl, and ObjCImplDecl. +/// +class ObjCContainerDecl : public NamedDecl, public DeclContext { + // These two locations in the range mark the end of the method container. + // The first points to the '@' token, and the second to the 'end' token. + SourceRange AtEnd; +public: + + ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id) + : NamedDecl(DK, DC, L, Id), DeclContext(DK) {} + + virtual ~ObjCContainerDecl() {} + + // Iterator access to properties. + typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; + prop_iterator prop_begin() const { + return prop_iterator(decls_begin()); + } + prop_iterator prop_end() const { + return prop_iterator(decls_end()); + } + + // Iterator access to instance/class methods. + typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; + method_iterator meth_begin() const { + return method_iterator(decls_begin()); + } + method_iterator meth_end() const { + return method_iterator(decls_end()); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isInstanceMethod> + instmeth_iterator; + instmeth_iterator instmeth_begin() const { + return instmeth_iterator(decls_begin()); + } + instmeth_iterator instmeth_end() const { + return instmeth_iterator(decls_end()); + } + + typedef filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isClassMethod> + classmeth_iterator; + classmeth_iterator classmeth_begin() const { + return classmeth_iterator(decls_begin()); + } + classmeth_iterator classmeth_end() const { + return classmeth_iterator(decls_end()); + } + + // Get the local instance/class method declared in this interface. + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel) const { + return getMethod(Sel, true/*isInstance*/); + } + ObjCMethodDecl *getClassMethod(Selector Sel) const { + return getMethod(Sel, false/*isInstance*/); + } + ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; + + ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; + + // Marks the end of the container. + SourceRange getAtEndRange() const { + return AtEnd; + } + void setAtEndRange(SourceRange atEnd) { + AtEnd = atEnd; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(getLocation(), getAtEndRange().getEnd()); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCContainerDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= ObjCContainerFirst && + K <= ObjCContainerLast; + } + + static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { + return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D)); + } + static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC)); + } +}; + +/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: +/// +/// // MostPrimitive declares no super class (not particularly useful). +/// @interface MostPrimitive +/// // no instance variables or methods. +/// @end +/// +/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). +/// @interface NSResponder : NSObject <NSCoding> +/// { // instance variables are represented by ObjCIvarDecl. +/// id nextResponder; // nextResponder instance variable. +/// } +/// - (NSResponder *)nextResponder; // return a pointer to NSResponder. +/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer +/// @end // to an NSEvent. +/// +/// Unlike C/C++, forward class declarations are accomplished with @class. +/// Unlike C/C++, @class allows for a list of classes to be forward declared. +/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes +/// typically inherit from NSObject (an exception is NSProxy). +/// +class ObjCInterfaceDecl : public ObjCContainerDecl { + /// TypeForDecl - This indicates the Type object that represents this + /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType + mutable Type *TypeForDecl; + friend class ASTContext; + + /// Class's super class. + ObjCInterfaceDecl *SuperClass; + + /// Protocols referenced in interface header declaration + ObjCProtocolList ReferencedProtocols; + + /// List of categories defined for this class. + /// FIXME: Why is this a linked list?? + ObjCCategoryDecl *CategoryList; + + bool ForwardDecl:1; // declared with @class. + bool InternalInterface:1; // true - no @interface for @implementation + + SourceLocation ClassLoc; // location of the class identifier. + SourceLocation SuperClassLoc; // location of the super class identifier. + SourceLocation EndLoc; // marks the '>', '}', or identifier. + + ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + SourceLocation CLoc, bool FD, bool isInternal); + + virtual ~ObjCInterfaceDecl() {} + +public: + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation atLoc, + IdentifierInfo *Id, + SourceLocation ClassLoc = SourceLocation(), + bool ForwardDecl = false, + bool isInternal = false); + const ObjCProtocolList &getReferencedProtocols() const { + return ReferencedProtocols; + } + + ObjCImplementationDecl *getImplementation() const; + void setImplementation(ObjCImplementationDecl *ImplD); + + ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const; + + // Get the local instance/class method declared in a category. + ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const; + ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const; + ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const { + return isInstance ? getInstanceMethod(Sel) + : getClassMethod(Sel); + } + + 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(); + } + protocol_loc_iterator protocol_loc_end() const { + return ReferencedProtocols.loc_end(); + } + unsigned protocol_size() const { return ReferencedProtocols.size(); } + + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } + ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); + } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } + + /// setProtocolList - Set the list of protocols that this interface + /// implements. + void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, + const SourceLocation *Locs, ASTContext &C) { + 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, + unsigned Num, + const SourceLocation *Locs, + ASTContext &C); + + bool isForwardDecl() const { return ForwardDecl; } + void setForwardDecl(bool val) { ForwardDecl = val; } + + ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } + void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } + + ObjCCategoryDecl* getCategoryList() const { return CategoryList; } + void setCategoryList(ObjCCategoryDecl *category) { + CategoryList = category; + } + + ObjCCategoryDecl* getClassExtension() const; + + ObjCPropertyDecl + *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; + + /// isSuperClassOf - Return true if this class is the specified class or is a + /// super class of the specified interface class. + bool isSuperClassOf(const ObjCInterfaceDecl *I) const { + // If RHS is derived from LHS it is OK; else it is not OK. + while (I != NULL) { + if (this == I) + return true; + I = I->getSuperClass(); + } + return false; + } + + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, + ObjCInterfaceDecl *&ClassDeclared); + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) { + ObjCInterfaceDecl *ClassDeclared; + return lookupInstanceVariable(IVarName, ClassDeclared); + } + + // 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 *lookupClassMethod(Selector Sel) const { + return lookupMethod(Sel, false/*isInstance*/); + } + ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); + + // Lookup a method in the classes implementation hierarchy. + ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel); + + // Location information, modeled after the Stmt API. + SourceLocation getLocStart() const { return getLocation(); } // '@'interface + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; } + + void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; } + SourceLocation getClassLoc() const { return ClassLoc; } + void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; } + SourceLocation getSuperClassLoc() const { return 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; } + + /// ClassImplementsProtocol - Checks that 'lProto' protocol + /// has been implemented in IDecl class, its super class or categories (if + /// lookupCategory is true). + bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, + bool lookupCategory, + bool RHSIsQualifiedID = false); + + // Low-level accessor + Type *getTypeForDecl() const { return TypeForDecl; } + void setTypeForDecl(Type *TD) const { TypeForDecl = TD; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCInterfaceDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCInterface; } +}; + +/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC +/// instance variables are identical to C. The only exception is Objective-C +/// supports C++ style access control. For example: +/// +/// @interface IvarExample : NSObject +/// { +/// id defaultToProtected; +/// @public: +/// id canBePublic; // same as C++. +/// @protected: +/// id canBeProtected; // same as C++. +/// @package: +/// id canBePackage; // framework visibility (not available in C++). +/// } +/// +class ObjCIvarDecl : public FieldDecl { +public: + enum AccessControl { + None, Private, Protected, Public, Package + }; + +private: + ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) + : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), + DeclAccess(ac) {} + +public: + static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, + SourceLocation L, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, + AccessControl ac, Expr *BW = NULL); + + /// \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; + + void setAccessControl(AccessControl ac) { DeclAccess = ac; } + + AccessControl getAccessControl() const { return AccessControl(DeclAccess); } + + AccessControl getCanonicalAccessControl() const { + return DeclAccess == None ? Protected : AccessControl(DeclAccess); + } + + // 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: + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum + unsigned DeclAccess : 3; +}; + + +/// ObjCAtDefsFieldDecl - Represents a field declaration created by an +/// @defs(...). +class ObjCAtDefsFieldDecl : public FieldDecl { +private: + ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + QualType T, Expr *BW) + : FieldDecl(ObjCAtDefsField, DC, L, Id, T, + /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? + BW, /*Mutable=*/false) {} + +public: + static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + IdentifierInfo *Id, QualType T, + Expr *BW); + + virtual void Destroy(ASTContext& C); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCAtDefsField; } +}; + +/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols +/// declare a pure abstract type (i.e no instance variables are permitted). +/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ +/// feature with nice semantics and lousy syntax:-). Here is an example: +/// +/// @protocol NSDraggingInfo <refproto1, refproto2> +/// - (NSWindow *)draggingDestinationWindow; +/// - (NSImage *)draggedImage; +/// @end +/// +/// This says that NSDraggingInfo requires two methods and requires everything +/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as +/// well. +/// +/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo> +/// @end +/// +/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and +/// protocols are in distinct namespaces. For example, Cocoa defines both +/// an NSObject protocol and class (which isn't allowed in Java). As a result, +/// protocols are referenced using angle brackets as follows: +/// +/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; +/// +class ObjCProtocolDecl : public ObjCContainerDecl { + /// Referenced protocols + ObjCProtocolList ReferencedProtocols; + + bool isForwardProtoDecl; // declared with @protocol. + + SourceLocation EndLoc; // marks the '>' or identifier. + + ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) + : ObjCContainerDecl(ObjCProtocol, DC, L, Id), + isForwardProtoDecl(true) { + } + + virtual ~ObjCProtocolDecl() {} + +public: + static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id); + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + const ObjCProtocolList &getReferencedProtocols() const { + return ReferencedProtocols; + } + 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(); + } + protocol_loc_iterator protocol_loc_end() const { + return ReferencedProtocols.loc_end(); + } + 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); + } + + ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); + + // 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 *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 getLocation(); } // '@'protocol + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; } + + 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; } +}; + +/// 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 *ForwardDecls; + unsigned NumDecls; + + ObjCClassDecl(DeclContext *DC, SourceLocation L, + ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, + unsigned nElts, ASTContext &C); + virtual ~ObjCClassDecl() {} +public: + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + ObjCInterfaceDecl *const *Elts = 0, + const SourceLocation *Locs = 0, + unsigned nElts = 0); + + virtual SourceRange getSourceRange() const; + + typedef const ObjCClassRef* iterator; + iterator begin() const { return ForwardDecls; } + iterator end() const { return ForwardDecls + NumDecls; } + unsigned size() const { return NumDecls; } + + /// setClassList - Set the list of forward classes. + void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num); + + 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); + virtual ~ObjCForwardProtocolDecl() {} + +public: + static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ObjCProtocolDecl *const *Elts, + unsigned Num, + const SourceLocation *Locs); + + static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L) { + return Create(C, DC, L, 0, 0, 0); + } + + /// Destroy - Call destructors and release memory. + virtual void Destroy(ASTContext& C); + + 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(); + } + protocol_loc_iterator protocol_loc_end() const { + return ReferencedProtocols.loc_end(); + } + + 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; } +}; + +/// ObjCCategoryDecl - Represents a category declaration. A category allows +/// you to add methods to an existing class (without subclassing or modifying +/// the original class interface or implementation:-). Categories don't allow +/// you to add instance data. The following example adds "myMethod" to all +/// NSView's within a process: +/// +/// @interface NSView (MyViewMethods) +/// - myMethod; +/// @end +/// +/// Categories also allow you to split the implementation of a class across +/// several files (a feature more naturally supported in C++). +/// +/// Categories were originally inspired by dynamic languages such as Common +/// Lisp and Smalltalk. More traditional class-based languages (C++, Java) +/// don't support this level of dynamism, which is both powerful and dangerous. +/// +class ObjCCategoryDecl : public ObjCContainerDecl { + /// Interface belonging to this category + ObjCInterfaceDecl *ClassInterface; + + /// referenced protocols in this category. + ObjCProtocolList ReferencedProtocols; + + /// Next category belonging to this class. + /// FIXME: this should not be a singly-linked list. Move storage elsewhere. + ObjCCategoryDecl *NextClassCategory; + + /// \brief The location of the '@' in '@interface' + SourceLocation AtLoc; + + /// \brief The location of the category name in this declaration. + SourceLocation CategoryNameLoc; + + ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, + SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, + IdentifierInfo *Id) + : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id), + ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc), + CategoryNameLoc(CategoryNameLoc) { + } +public: + + static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation AtLoc, + SourceLocation ClassNameLoc, + SourceLocation CategoryNameLoc, + IdentifierInfo *Id); + + ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } + const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } + void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; } + + ObjCCategoryImplDecl *getImplementation() const; + void setImplementation(ObjCCategoryImplDecl *ImplD); + + /// 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); + } + + const ObjCProtocolList &getReferencedProtocols() const { + return ReferencedProtocols; + } + + typedef ObjCProtocolList::iterator protocol_iterator; + protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} + 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_end() const { + return ReferencedProtocols.loc_end(); + } + + ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } + void setNextClassCategory(ObjCCategoryDecl *Cat) { + NextClassCategory = Cat; + } + void insertNextClassCategory() { + NextClassCategory = ClassInterface->getCategoryList(); + ClassInterface->setCategoryList(this); + } + + bool IsClassExtension() const { return getIdentifier() == 0; } + + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { + return ivar_iterator(decls_begin()); + } + ivar_iterator ivar_end() const { + return ivar_iterator(decls_end()); + } + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); + } + bool ivar_empty() const { + return ivar_begin() == ivar_end(); + } + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation At) { AtLoc = At; } + + SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } + void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, getAtEndRange().getEnd()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCCategoryDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCCategory; } +}; + +class ObjCImplDecl : public ObjCContainerDecl { + /// Class interface for this class/category implementation + ObjCInterfaceDecl *ClassInterface; + +protected: + ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L, + ObjCInterfaceDecl *classInterface) + : ObjCContainerDecl(DK, DC, L, + classInterface? classInterface->getIdentifier() : 0), + ClassInterface(classInterface) {} + +public: + virtual ~ObjCImplDecl() {} + + const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } + ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } + void setClassInterface(ObjCInterfaceDecl *IFace); + + void addInstanceMethod(ObjCMethodDecl *method) { + // FIXME: Context should be set correctly before we get here. + method->setLexicalDeclContext(this); + addDecl(method); + } + void addClassMethod(ObjCMethodDecl *method) { + // FIXME: Context should be set correctly before we get here. + method->setLexicalDeclContext(this); + addDecl(method); + } + + void addPropertyImplementation(ObjCPropertyImplDecl *property); + + ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; + ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; + + // Iterator access to properties. + typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; + propimpl_iterator propimpl_begin() const { + return propimpl_iterator(decls_begin()); + } + propimpl_iterator propimpl_end() const { + return propimpl_iterator(decls_end()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCImplDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= ObjCImplFirst && K <= ObjCImplLast; + } +}; + +/// ObjCCategoryImplDecl - An object of this class encapsulates a category +/// @implementation declaration. If a category class has declaration of a +/// property, its implementation must be specified in the category's +/// @implementation declaration. Example: +/// @interface I @end +/// @interface I(CATEGORY) +/// @property int p1, d1; +/// @end +/// @implementation I(CATEGORY) +/// @dynamic p1,d1; +/// @end +/// +/// ObjCCategoryImplDecl +class ObjCCategoryImplDecl : public ObjCImplDecl { + // Category name + IdentifierInfo *Id; + + ObjCCategoryImplDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl *classInterface) + : ObjCImplDecl(ObjCCategoryImpl, DC, L, classInterface), Id(Id) {} +public: + static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl *classInterface); + + /// getIdentifier - Get the identifier that names the category + /// interface associated with this implementation. + /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier() + /// to mean something different. For example: + /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() + /// returns the class interface name, whereas + /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() + /// returns the category name. + IdentifierInfo *getIdentifier() const { + return Id; + } + void setIdentifier(IdentifierInfo *II) { Id = II; } + + ObjCCategoryDecl *getCategoryDecl() const; + + /// getName - Get the name of identifier for the class interface associated + /// with this implementation as a StringRef. + // + // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean + // something different. + llvm::StringRef getName() const { + return Id ? Id->getNameStart() : ""; + } + + /// getNameAsCString - Get the name of identifier for the class + /// interface associated with this implementation as a C string + /// (const char*). + // + // FIXME: Deprecated, move clients to getName(). + const char *getNameAsCString() const { + return Id ? Id->getNameStart() : ""; + } + + /// @brief Get the name of the class associated with this interface. + // + // FIXME: Deprecated, move clients to getName(). + std::string getNameAsString() const { + return getName(); + } + + 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;} +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ObjCCategoryImplDecl *CID); + +/// ObjCImplementationDecl - Represents a class definition - this is where +/// method definitions are specified. For example: +/// +/// @code +/// @implementation MyClass +/// - (void)myMethod { /* do something */ } +/// @end +/// @endcode +/// +/// Typically, instance variables are specified in the class interface, +/// *not* in the implementation. Nevertheless (for legacy reasons), we +/// allow instance variables to be specified in the implementation. When +/// specified, they need to be *identical* to the interface. +/// +class ObjCImplementationDecl : public ObjCImplDecl { + /// Implementation Class's super class. + ObjCInterfaceDecl *SuperClass; + /// Support for ivar initialization. + /// IvarInitializers - The arguments used to initialize the ivars + CXXBaseOrMemberInitializer **IvarInitializers; + unsigned NumIvarInitializers; + + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, + ObjCInterfaceDecl *classInterface, + ObjCInterfaceDecl *superDecl) + : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} +public: + static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ObjCInterfaceDecl *classInterface, + ObjCInterfaceDecl *superDecl); + + /// init_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer **init_iterator; + + /// init_const_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer * 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; + } + /// end() - Retrieve an iterator past the last initializer. + init_const_iterator init_end() const { + return IvarInitializers + NumIvarInitializers; + } + /// getNumArgs - Number of ivars which must be initialized. + unsigned getNumIvarInitializers() const { + return NumIvarInitializers; + } + + void setNumIvarInitializers(unsigned numNumIvarInitializers) { + NumIvarInitializers = numNumIvarInitializers; + } + + void setIvarInitializers(ASTContext &C, + CXXBaseOrMemberInitializer ** initializers, + unsigned numInitializers); + + /// getIdentifier - Get the identifier that names the class + /// interface associated with this implementation. + IdentifierInfo *getIdentifier() const { + return getClassInterface()->getIdentifier(); + } + + /// getName - Get the name of identifier for the class interface associated + /// with this implementation as a StringRef. + // + // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean + // something different. + llvm::StringRef getName() const { + assert(getIdentifier() && "Name is not a simple identifier"); + return getIdentifier()->getName(); + } + + /// getNameAsCString - Get the name of identifier for the class + /// interface associated with this implementation as a C string + /// (const char*). + // + // FIXME: Move to StringRef API. + const char *getNameAsCString() const { + return getName().data(); + } + + /// @brief Get the name of the class associated with this interface. + // + // FIXME: Move to StringRef API. + std::string getNameAsString() const { + return getName(); + } + + const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } + ObjCInterfaceDecl *getSuperClass() { return SuperClass; } + + void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } + + typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; + ivar_iterator ivar_begin() const { + return ivar_iterator(decls_begin()); + } + ivar_iterator ivar_end() const { + return ivar_iterator(decls_end()); + } + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); + } + bool ivar_empty() const { + return ivar_begin() == ivar_end(); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCImplementationDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCImplementation; } +}; + +llvm::raw_ostream &operator<<(llvm::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 { + /// Class that this is an alias of. + ObjCInterfaceDecl *AliasedClass; + + ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl* aliasedClass) + : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {} +public: + static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, + ObjCInterfaceDecl* aliasedClass); + + const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } + ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } + void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCCompatibleAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; } + +}; + +/// ObjCPropertyDecl - Represents one property declaration in an interface. +/// For example: +/// @property (assign, readwrite) int MyProperty; +/// +class ObjCPropertyDecl : public NamedDecl { +public: + enum PropertyAttributeKind { + OBJC_PR_noattr = 0x00, + OBJC_PR_readonly = 0x01, + OBJC_PR_getter = 0x02, + OBJC_PR_assign = 0x04, + OBJC_PR_readwrite = 0x08, + OBJC_PR_retain = 0x10, + OBJC_PR_copy = 0x20, + OBJC_PR_nonatomic = 0x40, + OBJC_PR_setter = 0x80 + }; + + enum SetterKind { Assign, Retain, Copy }; + enum PropertyControl { None, Required, Optional }; +private: + SourceLocation AtLoc; // location of @property + QualType DeclType; + unsigned PropertyAttributes : 8; + + // @required/@optional + unsigned PropertyImplementation : 2; + + Selector GetterName; // getter name of NULL if no getter + Selector SetterName; // setter name of NULL if no setter + + ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method + ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method + ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property + + ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation AtLocation, QualType T) + : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T), + PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None), + GetterName(Selector()), + SetterName(Selector()), + GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {} +public: + static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + IdentifierInfo *Id, SourceLocation AtLocation, + QualType T, + PropertyControl propControl = None); + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + + QualType getType() const { return DeclType; } + void setType(QualType T) { DeclType = T; } + + PropertyAttributeKind getPropertyAttributes() const { + return PropertyAttributeKind(PropertyAttributes); + } + void setPropertyAttributes(PropertyAttributeKind PRVal) { + PropertyAttributes |= PRVal; + } + + void makeitReadWriteAttribute(void) { + PropertyAttributes &= ~OBJC_PR_readonly; + PropertyAttributes |= OBJC_PR_readwrite; + } + + // Helper methods for accessing attributes. + + /// isReadOnly - Return true iff the property has a setter. + bool isReadOnly() const { + return (PropertyAttributes & OBJC_PR_readonly); + } + + /// getSetterKind - Return the method used for doing assignment in + /// the property setter. This is only valid if the property has been + /// defined to have a setter. + SetterKind getSetterKind() const { + if (PropertyAttributes & OBJC_PR_retain) + return Retain; + if (PropertyAttributes & OBJC_PR_copy) + return Copy; + return Assign; + } + + Selector getGetterName() const { return GetterName; } + void setGetterName(Selector Sel) { GetterName = Sel; } + + Selector getSetterName() const { return SetterName; } + void setSetterName(Selector Sel) { SetterName = Sel; } + + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } + void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } + + ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } + void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } + + // Related to @optional/@required declared in @protocol + void setPropertyImplementation(PropertyControl pc) { + PropertyImplementation = pc; + } + PropertyControl getPropertyImplementation() const { + return PropertyControl(PropertyImplementation); + } + + void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { + PropertyIvarDecl = Ivar; + } + ObjCIvarDecl *getPropertyIvarDecl() const { + return PropertyIvarDecl; + } + + /// Lookup a property by name in the specified DeclContext. + static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, + IdentifierInfo *propertyID); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ObjCPropertyDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ObjCProperty; } +}; + +/// ObjCPropertyImplDecl - Represents implementation declaration of a property +/// in a class or category implementation block. For example: +/// @synthesize prop1 = ivar1; +/// +class ObjCPropertyImplDecl : public Decl { +public: + enum Kind { + Synthesize, + Dynamic + }; +private: + SourceLocation AtLoc; // location of @synthesize or @dynamic + /// 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; + + ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, + ObjCPropertyDecl *property, + Kind PK, + ObjCIvarDecl *ivarDecl) + : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), + PropertyDecl(property), PropertyIvarDecl(ivarDecl), + GetterCXXConstructor(0), SetterCXXAssignment(0) { + assert (PK == Dynamic || PropertyIvarDecl); + } + +public: + static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation atLoc, SourceLocation L, + ObjCPropertyDecl *property, + Kind PK, + ObjCIvarDecl *ivarDecl); + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, getLocation()); + } + SourceLocation getLocStart() const { return AtLoc; } + void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } + + ObjCPropertyDecl *getPropertyDecl() const { + return PropertyDecl; + } + void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; } + + Kind getPropertyImplementation() const { + return PropertyIvarDecl ? Synthesize : Dynamic; + } + + ObjCIvarDecl *getPropertyIvarDecl() const { + return PropertyIvarDecl; + } + void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + + Expr *getGetterCXXConstructor() const { + return GetterCXXConstructor; + } + void setGetterCXXConstructor(Expr *getterCXXConstructor) { + GetterCXXConstructor = getterCXXConstructor; + } + + Expr *getSetterCXXAssignment() const { + return SetterCXXAssignment; + } + 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; } +}; + +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h new file mode 100644 index 0000000..b7b90b1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h @@ -0,0 +1,1433 @@ +//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C++ template declaration subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H +#define LLVM_CLANG_AST_DECLTEMPLATE_H + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" +#include "llvm/ADT/PointerUnion.h" +#include <limits> + +namespace clang { + +class TemplateParameterList; +class TemplateDecl; +class FunctionTemplateDecl; +class ClassTemplateDecl; +class ClassTemplatePartialSpecializationDecl; +class TemplateTypeParmDecl; +class NonTypeTemplateParmDecl; +class TemplateTemplateParmDecl; + +/// \brief Stores a template parameter of any kind. +typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, + TemplateTemplateParmDecl*> TemplateParameter; + +/// TemplateParameterList - Stores a list of template parameters for a +/// TemplateDecl and its derived classes. +class TemplateParameterList { + /// The location of the 'template' keyword. + SourceLocation TemplateLoc; + + /// The locations of the '<' and '>' angle brackets. + SourceLocation LAngleLoc, RAngleLoc; + + /// The number of template parameters in this template + /// parameter list. + unsigned NumParams; + + TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, + NamedDecl **Params, unsigned NumParams, + SourceLocation RAngleLoc); + +public: + static TemplateParameterList *Create(ASTContext &C, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + NamedDecl **Params, + unsigned NumParams, + SourceLocation RAngleLoc); + + /// iterator - Iterates through the template parameters in this list. + typedef NamedDecl** iterator; + + /// const_iterator - Iterates through the template parameters in this list. + typedef NamedDecl* const* const_iterator; + + iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); } + const_iterator begin() const { + return reinterpret_cast<NamedDecl * const *>(this + 1); + } + iterator end() { return begin() + NumParams; } + const_iterator end() const { return begin() + NumParams; } + + unsigned size() const { return NumParams; } + + NamedDecl* getParam(unsigned Idx) { + assert(Idx < size() && "Template parameter index out-of-range"); + return begin()[Idx]; + } + + const NamedDecl* getParam(unsigned Idx) const { + assert(Idx < size() && "Template parameter index out-of-range"); + return begin()[Idx]; + } + + /// \btief Returns the minimum number of arguments needed to form a + /// template specialization. This may be fewer than the number of + /// template parameters, if some of the parameters have default + /// arguments or if there is a parameter pack. + unsigned getMinRequiredArguments() const; + + /// \brief Get the depth of this template parameter list in the set of + /// template parameter lists. + /// + /// The first template parameter list in a declaration will have depth 0, + /// the second template parameter list will have depth 1, etc. + unsigned getDepth() const; + + SourceLocation getTemplateLoc() const { return TemplateLoc; } + SourceLocation getLAngleLoc() const { return LAngleLoc; } + SourceLocation getRAngleLoc() const { return RAngleLoc; } + + SourceRange getSourceRange() const { + return SourceRange(TemplateLoc, RAngleLoc); + } +}; + +/// \brief A helper class for making template argument lists. +class TemplateArgumentListBuilder { + TemplateArgument *StructuredArgs; + unsigned MaxStructuredArgs; + unsigned NumStructuredArgs; + + llvm::SmallVector<TemplateArgument, 4> FlatArgs; + unsigned MaxFlatArgs; + unsigned NumFlatArgs; + + bool AddingToPack; + unsigned PackBeginIndex; + +public: + TemplateArgumentListBuilder(const TemplateParameterList *Parameters, + unsigned NumTemplateArgs) + : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), + NumStructuredArgs(0), FlatArgs(0), + MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), + AddingToPack(false), PackBeginIndex(0) { } + + void Append(const TemplateArgument &Arg); + void BeginPack(); + void EndPack(); + + unsigned flatSize() const { return FlatArgs.size(); } + const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); } + + unsigned structuredSize() const { + // If we don't have any structured args, just reuse the flat size. + if (!StructuredArgs) + return flatSize(); + + return NumStructuredArgs; + } + const TemplateArgument *getStructuredArguments() const { + // If we don't have any structured args, just reuse the flat args. + if (!StructuredArgs) + return getFlatArguments(); + + return StructuredArgs; + } +}; + +/// \brief A template argument list. +/// +/// FIXME: In the future, this class will be extended to support +/// variadic templates and member templates, which will make some of +/// the function names below make more sense. +class TemplateArgumentList { + /// \brief The template argument list. + /// + /// The integer value will be non-zero to indicate that this + /// template argument list does own the pointer. + llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; + + /// \brief The number of template arguments in this template + /// argument list. + unsigned NumFlatArguments; + + llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; + unsigned NumStructuredArguments; + + TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL + void operator=(const TemplateArgumentList &Other); // DO NOT IMPL +public: + /// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs' + /// it copies them into a locally new[]'d array. If passed "false", then it + /// just references the array passed in. This is only safe if the builder + /// outlives it, but saves a copy. + TemplateArgumentList(ASTContext &Context, + TemplateArgumentListBuilder &Builder, + bool TakeArgs); + + /// Produces a shallow copy of the given template argument list. This + /// 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 way. + explicit TemplateArgumentList(const TemplateArgumentList *Other); + + /// Used to release the memory associated with a TemplateArgumentList + /// object. FIXME: This is currently not called anywhere, but the + /// memory will still be freed when using a BumpPtrAllocator. + void Destroy(ASTContext &C); + + ~TemplateArgumentList(); + + /// \brief Retrieve the template argument at a given index. + const TemplateArgument &get(unsigned Idx) const { + assert(Idx < NumFlatArguments && "Invalid template argument index"); + return getFlatArgumentList()[Idx]; + } + + /// \brief Retrieve the template argument at a given index. + const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } + + /// \brief Retrieve the number of template arguments in this + /// template argument list. + unsigned size() const { return NumFlatArguments; } + + /// \brief Retrieve the number of template arguments in the + /// flattened template argument list. + unsigned flat_size() const { return NumFlatArguments; } + + /// \brief Retrieve the flattened template argument list. + const TemplateArgument *getFlatArgumentList() const { + return FlatArguments.getPointer(); + } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Templates +//===----------------------------------------------------------------------===// + +/// TemplateDecl - The base class of all kinds of template declarations (e.g., +/// class, function, etc.). The TemplateDecl class stores the list of template +/// parameters and a reference to the templated scoped declaration: the +/// underlying AST node. +class TemplateDecl : public NamedDecl { +protected: + // This is probably never used. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { } + + // Construct a template decl with the given name and parameters. + // Used when there is not templated element (tt-params, alias?). + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) { } + + // Construct a template decl with name, parameters, and templated element. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), + TemplateParams(Params) { } +public: + ~TemplateDecl(); + + /// Get the list of template parameters + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + /// Get the underlying, templated declaration. + NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classof(const TemplateTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= TemplateFirst && K <= TemplateLast; + } + +protected: + NamedDecl *TemplatedDecl; + TemplateParameterList* TemplateParams; +}; + +/// \brief Provides information about a function template specialization, +/// which is a FunctionDecl that has been explicitly specialization or +/// instantiated from a function template. +class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { +public: + /// \brief The function template specialization that this structure + /// describes. + FunctionDecl *Function; + + /// \brief The function template from which this function template + /// specialization was generated. + /// + /// The two bits are contain the top 4 values of TemplateSpecializationKind. + llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template; + + /// \brief The template arguments used to produce the function template + /// specialization from the function template. + const TemplateArgumentList *TemplateArguments; + + /// \brief The template arguments as written in the sources, if provided. + const TemplateArgumentListInfo *TemplateArgumentsAsWritten; + + /// \brief The point at which this function template specialization was + /// first instantiated. + SourceLocation PointOfInstantiation; + + /// \brief Retrieve the template from which this function was specialized. + FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } + + /// \brief Determine what kind of template specialization this is. + TemplateSpecializationKind getTemplateSpecializationKind() const { + return (TemplateSpecializationKind)(Template.getInt() + 1); + } + + /// \brief Set the template specialization kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { + assert(TSK != TSK_Undeclared && + "Cannot encode TSK_Undeclared for a function template specialization"); + Template.setInt(TSK - 1); + } + + /// \brief Retrieve the first point of instantiation of this function + /// template specialization. + /// + /// The point of instantiation may be an invalid source location if this + /// function has yet to be instantiated. + 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->getFlatArgumentList(), + TemplateArguments->flat_size(), + Function->getASTContext()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, ASTContext &Context) { + ID.AddInteger(NumTemplateArgs); + for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + TemplateArgs[Arg].Profile(ID, Context); + } +}; + +/// \brief Provides information a specialization of a member of a class +/// template, which may be a member function, static data member, or +/// member class. +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 + MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK) + : MemberAndTSK(IF, TSK - 1), PointOfInstantiation() { + 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 && + "Cannot encode undeclared template specializations for members"); + MemberAndTSK.setInt(TSK - 1); + } + + /// \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; + } + + /// \brief Set the first point of instantiation. + void setPointOfInstantiation(SourceLocation POI) { + PointOfInstantiation = POI; + } +}; + +/// \brief Provides information about a dependent function-template +/// specialization declaration. Since explicit function template +/// specialization and instantiation declarations can only appear in +/// namespace scope, and you can only specialize a member of a +/// fully-specialized class, the only way to get one of these is in +/// a friend declaration like the following: +/// +/// template <class T> void foo(T); +/// template <class T> class A { +/// friend void foo<>(T); +/// }; +class DependentFunctionTemplateSpecializationInfo { + union { + // Force sizeof to be a multiple of sizeof(void*) so that the + // trailing data is aligned. + void *Aligner; + + struct { + /// The number of potential template candidates. + unsigned NumTemplates; + + /// The number of template arguments. + unsigned NumArgs; + } d; + }; + + /// The locations of the left and right angle brackets. + SourceRange AngleLocs; + + FunctionTemplateDecl * const *getTemplates() const { + return reinterpret_cast<FunctionTemplateDecl*const*>(this+1); + } + + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc*>( + &getTemplates()[getNumTemplates()]); + } + +public: + DependentFunctionTemplateSpecializationInfo( + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + /// \brief Returns the number of function templates that this might + /// be a specialization of. + unsigned getNumTemplates() const { + return d.NumTemplates; + } + + /// \brief Returns the i'th template candidate. + FunctionTemplateDecl *getTemplate(unsigned I) const { + assert(I < getNumTemplates() && "template index out of range"); + return getTemplates()[I]; + } + + /// \brief Returns the number of explicit template arguments that were given. + unsigned getNumTemplateArgs() const { + return d.NumArgs; + } + + /// \brief Returns the nth template argument. + const TemplateArgumentLoc &getTemplateArg(unsigned I) const { + assert(I < getNumTemplateArgs() && "template arg index out of range"); + return getTemplateArgs()[I]; + } + + SourceLocation getLAngleLoc() const { + return AngleLocs.getBegin(); + } + + SourceLocation getRAngleLoc() const { + return AngleLocs.getEnd(); + } +}; + +/// Declaration of a template function. +class FunctionTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + +protected: + /// \brief Data that is common to all of the declarations of a given + /// function template. + struct Common { + Common() : InstantiatedFromMember(0, false) { } + + /// \brief The function template specializations for this function + /// template, including explicit specializations and instantiations. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + + /// \brief The member function template from which this was most + /// directly instantiated (or null). + /// + /// The boolean value indicates whether this member function template + /// was explicitly specialized. + llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember; + }; + + /// \brief A pointer to the previous declaration (if this is a redeclaration) + /// or to the data that is common to all declarations of this function + /// template. + llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev; + + /// \brief Retrieves the "common" pointer shared by all + /// (re-)declarations of the same function template. Calling this routine + /// may implicitly allocate memory for the common pointer. + Common *getCommonPtr(); + + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), + CommonOrPrev((Common*)0) { } + +public: + void Destroy(ASTContext &C); + + /// Get the underlying function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast<FunctionDecl*>(TemplatedDecl); + } + + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { + return getCommonPtr()->Specializations; + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const FunctionTemplateDecl *getPreviousDeclaration() const { + return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + FunctionTemplateDecl *getPreviousDeclaration() { + return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + } + + /// \brief Set the previous declaration of this function template. + void setPreviousDeclaration(FunctionTemplateDecl *Prev) { + if (Prev) + CommonOrPrev = Prev; + } + + virtual FunctionTemplateDecl *getCanonicalDecl(); + + /// \brief Retrieve the member function template that this function template + /// was instantiated from. + /// + /// This routine will return non-NULL for member function templates of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> void f(); + /// }; + /// \endcode + /// + /// X<int>::A<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). + /// + /// \returns NULL if this is not an instantiation of a member function + /// template. + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(FTD); + } + + /// \brief Determines whether this template was a specialization of a + /// member template. + /// + /// In the following example, the function template \c X<int>::f is a + /// member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> void f(T, U); + /// }; + /// + /// template<> template<typename T> + /// void X<int>::f(int, T); + /// \endcode + 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); + } + + /// Create a template function node. + static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { return K == FunctionTemplate; } +}; + +//===----------------------------------------------------------------------===// +// Kinds of Template Parameters +//===----------------------------------------------------------------------===// + +/// The TemplateParmPosition class defines the position of a template parameter +/// within a template parameter list. Because template parameter can be listed +/// sequentially for out-of-line template members, each template parameter is +/// given a Depth - the nesting of template parameter scopes - and a Position - +/// the occurrence within the parameter list. +/// This class is inheritedly privately by different kinds of template +/// parameters and is not part of the Decl hierarchy. Just a facility. +class TemplateParmPosition { +protected: + // FIXME: This should probably never be called, but it's here as + TemplateParmPosition() + : Depth(0), Position(0) + { /* assert(0 && "Cannot create positionless template parameter"); */ } + + TemplateParmPosition(unsigned D, unsigned P) + : Depth(D), Position(P) + { } + + // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for + // position? Maybe? + unsigned Depth; + unsigned Position; + +public: + /// Get the nesting depth of the template parameter. + unsigned getDepth() const { return Depth; } + + /// Get the position of the template parameter within its parameter list. + unsigned getPosition() const { return Position; } + + /// Get the index of the template parameter within its parameter list. + unsigned getIndex() const { return Position; } +}; + +/// TemplateTypeParmDecl - Declaration of a template type parameter, +/// e.g., "T" in +/// @code +/// template<typename T> class vector; +/// @endcode +class TemplateTypeParmDecl : public TypeDecl { + /// \brief Whether this template type parameter was declaration with + /// the 'typename' keyword. If false, it was declared with the + /// 'class' keyword. + bool Typename : 1; + + /// \brief Whether this template type parameter inherited its + /// default argument. + bool InheritedDefault : 1; + + /// \brief Whether this is a parameter pack. + bool ParameterPack : 1; + + /// \brief The default template argument, if any. + TypeSourceInfo *DefaultArgument; + + TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + bool Typename, QualType Type, bool ParameterPack) + : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), + InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { + TypeForDecl = Type.getTypePtr(); + } + +public: + static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, bool Typename, + bool ParameterPack); + + /// \brief Whether this template type parameter was declared with + /// the 'typename' keyword. If not, it was declared with the 'class' + /// keyword. + bool wasDeclaredWithTypename() const { return Typename; } + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { return DefaultArgument != 0; } + + /// \brief Retrieve the default argument, if any. + QualType getDefaultArgument() const { return DefaultArgument->getType(); } + + /// \brief Retrieves the default argument's source information, if any. + TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; } + + /// \brief Retrieves the location of the default argument declaration. + SourceLocation getDefaultArgumentLoc() const; + + /// \brief Determines whether the default argument was inherited + /// from a previous declaration of this template. + bool defaultArgumentWasInherited() const { return InheritedDefault; } + + /// \brief Set the default argument for this template parameter, and + /// whether that default argument was inherited from another + /// declaration. + void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) { + DefaultArgument = DefArg; + InheritedDefault = Inherited; + } + + /// \brief Removes the default argument of this template parameter. + void removeDefaultArgument() { + DefaultArgument = 0; + InheritedDefault = false; + } + + /// \brief Retrieve the depth of the template parameter. + unsigned getDepth() const; + + /// \brief Retrieve the index of the template parameter. + unsigned getIndex() const; + + /// \brief Returns whether this is a parameter pack. + bool isParameterPack() const { return ParameterPack; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TemplateTypeParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TemplateTypeParm; } +}; + +/// NonTypeTemplateParmDecl - Declares a non-type template parameter, +/// e.g., "Size" in +/// @code +/// template<int Size> class array { }; +/// @endcode +class NonTypeTemplateParmDecl + : public VarDecl, protected TemplateParmPosition { + /// \brief The default template argument, if any. + Expr *DefaultArgument; + + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo) + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, + VarDecl::None), + TemplateParmPosition(D, P), DefaultArgument(0) + { } + +public: + static NonTypeTemplateParmDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + using TemplateParmPosition::getIndex; + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the default argument, if any. + Expr *getDefaultArgument() const { return DefaultArgument; } + + /// \brief Retrieve the location of the default argument, if any. + SourceLocation getDefaultArgumentLoc() const; + + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(Expr *DefArg) { + DefaultArgument = DefArg; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const NonTypeTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } +}; + +/// TemplateTemplateParmDecl - Declares a template template parameter, +/// e.g., "T" in +/// @code +/// template <template <typename> class T> class container { }; +/// @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 { + + /// \brief The default template argument, if any. + TemplateArgumentLoc DefaultArgument; + + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, + unsigned D, unsigned P, + IdentifierInfo *Id, TemplateParameterList *Params) + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P), DefaultArgument() + { } + +public: + static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, + TemplateParameterList *Params); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getPosition; + using TemplateParmPosition::getIndex; + + /// \brief Determine whether this template parameter has a default + /// argument. + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); + } + + /// \brief Retrieve the default argument, if any. + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } + + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(const TemplateArgumentLoc &DefArg) { + DefaultArgument = DefArg; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TemplateTemplateParmDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TemplateTemplateParm; } +}; + +/// \brief Represents a class template specialization, which refers to +/// a class template with a given set of template arguments. +/// +/// Class template specializations represent both explicit +/// specialization of class templates, as in the example below, and +/// implicit instantiations of class templates. +/// +/// \code +/// template<typename T> class array; +/// +/// template<> +/// class array<bool> { }; // class template specialization array<bool> +/// \endcode +class ClassTemplateSpecializationDecl + : public CXXRecordDecl, public llvm::FoldingSetNode { + + /// \brief Structure that stores information about a class template + /// specialization that was instantiated from a class template partial + /// specialization. + struct SpecializedPartialSpecialization { + /// \brief The class template partial specialization from which this + /// class template specialization was instantiated. + ClassTemplatePartialSpecializationDecl *PartialSpecialization; + + /// \brief The template argument list deduced for the class template + /// partial specialization itself. + TemplateArgumentList *TemplateArgs; + }; + + /// \brief The template that this specialization specializes + llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> + SpecializedTemplate; + + /// \brief The type-as-written of an explicit template specialization. + /// Does not apply to implicit specializations. + TypeSourceInfo *TypeAsWritten; + + /// \brief The template arguments used to describe this specialization. + TemplateArgumentList TemplateArgs; + + /// \brief The point where this template was instantiated (if any) + SourceLocation PointOfInstantiation; + + /// \brief The kind of specialization this declaration refers to. + /// Really a value of type TemplateSpecializationKind. + unsigned SpecializationKind : 3; + +protected: + ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, + DeclContext *DC, SourceLocation L, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgumentListBuilder &Builder, + ClassTemplateSpecializationDecl *PrevDecl); + +public: + static ClassTemplateSpecializationDecl * + Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgumentListBuilder &Builder, + ClassTemplateSpecializationDecl *PrevDecl); + + virtual void Destroy(ASTContext& C); + + virtual void getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const; + + /// \brief Retrieve the template that this specialization specializes. + ClassTemplateDecl *getSpecializedTemplate() const; + + /// \brief Retrieve the template arguments of the class template + /// specialization. + const TemplateArgumentList &getTemplateArgs() const { + return TemplateArgs; + } + + /// \brief Determine the kind of specialization that this + /// declaration represents. + TemplateSpecializationKind getSpecializationKind() const { + return static_cast<TemplateSpecializationKind>(SpecializationKind); + } + + void setSpecializationKind(TemplateSpecializationKind TSK) { + SpecializationKind = TSK; + } + + /// \brief Get the point of instantiation (if any), or null if none. + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; + } + + void setPointOfInstantiation(SourceLocation Loc) { + assert(Loc.isValid() && "point of instantiation must be valid!"); + PointOfInstantiation = Loc; + } + + /// \brief If this class template specialization is an instantiation of + /// a template (rather than an explicit specialization), return the + /// class template or class template partial specialization from which it + /// was instantiated. + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + getInstantiatedFrom() const { + if (getSpecializationKind() != TSK_ImplicitInstantiation && + getSpecializationKind() != TSK_ExplicitInstantiationDefinition && + getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) + return (ClassTemplateDecl*)0; + + if (SpecializedPartialSpecialization *PartialSpec + = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return PartialSpec->PartialSpecialization; + + return const_cast<ClassTemplateDecl*>( + SpecializedTemplate.get<ClassTemplateDecl*>()); + } + + /// \brief Retrieve the set of template arguments that should be used + /// to instantiate members of the class template or class template partial + /// specialization from which this class template specialization was + /// instantiated. + /// + /// \returns For a class template specialization instantiated from the primary + /// template, this function will return the same template arguments as + /// getTemplateArgs(). For a class template specialization instantiated from + /// a class template partial specialization, this function will return the + /// deduced template arguments for the class template partial specialization + /// itself. + const TemplateArgumentList &getTemplateInstantiationArgs() const { + if (SpecializedPartialSpecialization *PartialSpec + = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return *PartialSpec->TemplateArgs; + + return getTemplateArgs(); + } + + /// \brief Note that this class template specialization is actually an + /// instantiation of the given class template partial specialization whose + /// template arguments have been deduced. + void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, + TemplateArgumentList *TemplateArgs) { + SpecializedPartialSpecialization *PS + = new (getASTContext()) SpecializedPartialSpecialization(); + PS->PartialSpecialization = PartialSpec; + PS->TemplateArgs = TemplateArgs; + SpecializedTemplate = PS; + } + + /// \brief Sets the type of this specialization as it was written by + /// the user. This will be a class template specialization type. + void setTypeAsWritten(TypeSourceInfo *T) { + TypeAsWritten = T; + } + + /// \brief Gets the type of this specialization as it was written by + /// the user, if it was so written. + TypeSourceInfo *getTypeAsWritten() const { + return TypeAsWritten; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), + getASTContext()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, ASTContext &Context) { + ID.AddInteger(NumTemplateArgs); + for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + TemplateArgs[Arg].Profile(ID, Context); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == ClassTemplateSpecialization || + K == ClassTemplatePartialSpecialization; + } + + static bool classof(const ClassTemplateSpecializationDecl *) { + return true; + } + + static bool classof(const ClassTemplatePartialSpecializationDecl *) { + return true; + } +}; + +class ClassTemplatePartialSpecializationDecl + : public ClassTemplateSpecializationDecl { + /// \brief The list of template parameters + TemplateParameterList* TemplateParams; + + /// \brief The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? + TemplateArgumentLoc *ArgsAsWritten; + unsigned NumArgsAsWritten; + + /// \brief Sequence number indicating when this class template partial + /// 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 + /// 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 L, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgumentListBuilder &Builder, + TemplateArgumentLoc *ArgInfos, + unsigned NumArgInfos, + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + TK, DC, L, SpecializedTemplate, Builder, + PrevDecl), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), + InstantiatedFromMember(0, false) { } + +public: + static ClassTemplatePartialSpecializationDecl * + Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + TemplateArgumentListBuilder &Builder, + const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber); + + /// Get the list of template parameters + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + /// Get the template arguments as written. + TemplateArgumentLoc *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + + /// Get the number of template arguments as written. + unsigned getNumTemplateArgsAsWritten() const { + return NumArgsAsWritten; + } + + /// \brief Get the sequence number for this class template partial + /// specialization. + unsigned getSequenceNumber() const { return SequenceNumber; } + + /// \brief Retrieve the member class template partial specialization from + /// which this particular class template partial specialization was + /// instantiated. + /// + /// \code + /// template<typename T> + /// struct Outer { + /// template<typename U> struct Inner; + /// template<typename U> struct Inner<U*> { }; // #1 + /// }; + /// + /// Outer<float>::Inner<int*> ii; + /// \endcode + /// + /// In this example, the instantiation of \c Outer<float>::Inner<int*> will + /// end up instantiating the partial specialization + /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class + /// template partial specialization \c Outer<T>::Inner<U*>. Given + /// \c Outer<float>::Inner<U*>, this function would return + /// \c Outer<T>::Inner<U*>. + ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + return First->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *PartialSpec) { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + First->InstantiatedFromMember.setPointer(PartialSpec); + } + + /// \brief Determines whether this class template partial specialization + /// template was a specialization of a member partial specialization. + /// + /// In the following example, the member template partial specialization + /// \c X<int>::Inner<T*> is a member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> struct Inner; + /// template<typename U> struct Inner<U*>; + /// }; + /// + /// template<> template<typename T> + /// struct X<int>::Inner<T*> { /* ... */ }; + /// \endcode + bool isMemberSpecialization() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + return First->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + ClassTemplatePartialSpecializationDecl *First + = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration()); + assert(First->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + return First->InstantiatedFromMember.setInt(true); + } + + /// Retrieves the injected specialization type for this partial + /// specialization. This is not the same as the type-decl-type for + /// this partial specialization, which is an InjectedClassNameType. + QualType getInjectedSpecializationType() const { + assert(getTypeForDecl() && "partial specialization has no type set!"); + return cast<InjectedClassNameType>(getTypeForDecl()) + ->getInjectedSpecializationType(); + } + + // FIXME: Add Profile support! + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == ClassTemplatePartialSpecialization; + } + + static bool classof(const ClassTemplatePartialSpecializationDecl *) { + return true; + } +}; + +/// Declaration of a class template. +class ClassTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + +protected: + /// \brief Data that is common to all of the declarations of a given + /// class template. + struct Common { + Common() : InstantiatedFromMember(0, 0) {} + + /// \brief The class template specializations for this class + /// template, including explicit specializations and instantiations. + llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; + + /// \brief The class template partial specializations for this class + /// template. + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> + PartialSpecializations; + + /// \brief The injected-class-name type for this class template. + QualType InjectedClassNameType; + + /// \brief The templated member class from which this was most + /// directly instantiated (or null). + /// + /// The boolean value indicates whether this member class template + /// was explicitly specialized. + llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember; + }; + + // FIXME: Combine PreviousDeclaration with CommonPtr, as in + // FunctionTemplateDecl. + + /// \brief Previous declaration of this class template. + ClassTemplateDecl *PreviousDeclaration; + + /// \brief Pointer to the data that is common to all of the + /// declarations of this class template. + /// + /// The first declaration of a class template (e.g., the declaration + /// with no "previous declaration") owns this pointer. + Common *CommonPtr; + + ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl, + ClassTemplateDecl *PrevDecl, Common *CommonPtr) + : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), + PreviousDeclaration(PrevDecl), CommonPtr(CommonPtr) { } + + ~ClassTemplateDecl(); + +public: + /// Get the underlying class declarations of the template. + CXXRecordDecl *getTemplatedDecl() const { + return static_cast<CXXRecordDecl *>(TemplatedDecl); + } + + /// \brief Retrieve the previous declaration of this template. + ClassTemplateDecl *getPreviousDeclaration() const { + return PreviousDeclaration; + } + + virtual ClassTemplateDecl *getCanonicalDecl(); + + /// Create a class template node. + static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl, + ClassTemplateDecl *PrevDecl); + + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { + return CommonPtr->Specializations; + } + + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & + getPartialSpecializations() { + return CommonPtr->PartialSpecializations; + } + + /// \brief Retrieve the partial specializations as an ordered list. + void getPartialSpecializations( + llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); + + /// \brief Find a class template partial specialization with the given + /// type T. + /// + /// \brief A dependent type that names a specialization of this class + /// template. + /// + /// \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 Retrieve the template specialization type of the + /// injected-class-name for this class template. + /// + /// The injected-class-name for a class template \c X is \c + /// X<template-args>, where \c template-args is formed from the + /// template arguments that correspond to the template parameters of + /// \c X. For example: + /// + /// \code + /// template<typename T, int N> + /// struct array { + /// typedef array this_type; // "array" is equivalent to "array<T, N>" + /// }; + /// \endcode + QualType getInjectedClassNameSpecialization(ASTContext &Context); + + /// \brief Retrieve the member class template that this class template was + /// derived from. + /// + /// This routine will return non-NULL for templated member classes of + /// class templates. For example, given: + /// + /// \code + /// template <typename T> + /// struct X { + /// template <typename U> struct A {}; + /// }; + /// \endcode + /// + /// 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 TemplateClassDecl (whose parent is again + /// X<int>) for which getInstantiatedFromMemberTemplate() will return + /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD). + /// + /// \returns null if this is not an instantiation of a member class template. + ClassTemplateDecl *getInstantiatedFromMemberTemplate() const { + return CommonPtr->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { + assert(!CommonPtr->InstantiatedFromMember.getPointer()); + CommonPtr->InstantiatedFromMember.setPointer(CTD); + } + + /// \brief Determines whether this template was a specialization of a + /// member template. + /// + /// In the following example, the member template \c X<int>::Inner is a + /// member specialization. + /// + /// \code + /// template<typename T> + /// struct X { + /// template<typename U> struct Inner; + /// }; + /// + /// template<> template<typename T> + /// struct X<int>::Inner { /* ... */ }; + /// \endcode + bool isMemberSpecialization() { + return CommonPtr->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + assert(CommonPtr->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + CommonPtr->InstantiatedFromMember.setInt(true); + } + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { return K == ClassTemplate; } + + virtual void Destroy(ASTContext& C); +}; + +/// Declaration of a friend template. For example: +/// +/// template <typename T> class A { +/// friend class MyVector<T>; // not a friend template +/// template <typename U> friend class B; // friend template +/// template <typename U> friend class Foo<T>::Nested; // friend template +class FriendTemplateDecl : public Decl { +public: + typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; + +private: + // The number of template parameters; always non-zero. + unsigned NumParams; + + // The parameter list. + TemplateParameterList **Params; + + // The declaration that's a friend of this class. + FriendUnion Friend; + + // Location of the 'friend' specifier. + SourceLocation FriendLoc; + + + FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, + unsigned NParams, + TemplateParameterList **Params, + FriendUnion Friend, + SourceLocation FriendLoc) + : Decl(Decl::FriendTemplate, DC, Loc), + NumParams(NParams), + Params(Params), + Friend(Friend), + FriendLoc(FriendLoc) + {} + +public: + static FriendTemplateDecl *Create(ASTContext &Context, + DeclContext *DC, SourceLocation Loc, + unsigned NParams, + TemplateParameterList **Params, + FriendUnion Friend, + SourceLocation FriendLoc); + + /// If this friend declaration names a templated type (or + /// a dependent member type of a templated type), return that + /// type; otherwise return null. + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast<TypeSourceInfo*>(); + } + + /// If this friend declaration names a templated function (or + /// a member function of a templated type), return that type; + /// otherwise return null. + NamedDecl *getFriendDecl() const { + return Friend.dyn_cast<NamedDecl*>(); + } + + /// Retrieves the location of the 'friend' keyword. + SourceLocation getFriendLoc() const { + return FriendLoc; + } + + TemplateParameterList *getTemplateParameterList(unsigned i) const { + assert(i <= NumParams); + return Params[i]; + } + + unsigned getNumTemplateParameters() const { + return NumParams; + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } + static bool classof(const FriendTemplateDecl *D) { return true; } +}; + +/// Implementation of inline functions that require the template declarations +inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) + : Function(FTD) { } + +} /* end of namespace clang */ + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h new file mode 100644 index 0000000..140e5c0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h @@ -0,0 +1,55 @@ +//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- 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 DeclVisitor interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLVISITOR_H +#define LLVM_CLANG_AST_DECLVISITOR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclTemplate.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D)) + +/// \brief A simple visitor class that helps create declaration visitors. +template<typename ImplClass, typename RetTy=void> +class DeclVisitor { +public: + RetTy Visit(Decl *D) { + switch (D->getKind()) { + default: assert(false && "Decl that isn't part of DeclNodes.def!"); +#define DECL(Derived, Base) \ + case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl); +#define ABSTRACT_DECL(Derived, Base) +#include "clang/AST/DeclNodes.def" + } + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. +#define DECL(Derived, Base) \ + RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); } +#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base) +#include "clang/AST/DeclNodes.def" + + RetTy VisitDecl(Decl *D) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_DECLVISITOR_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h new file mode 100644 index 0000000..8a771d5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h @@ -0,0 +1,416 @@ +//===-- DeclarationName.h - Representation of declaration names -*- 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 DeclarationName and DeclarationNameTable classes. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H +#define LLVM_CLANG_AST_DECLARATIONNAME_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" +#include "clang/Basic/PartialDiagnostic.h" + +namespace llvm { + template <typename T> struct DenseMapInfo; +} + +namespace clang { + class CXXSpecialName; + class CXXOperatorIdName; + class CXXLiteralOperatorIdName; + class DeclarationNameExtra; + class IdentifierInfo; + class MultiKeywordSelector; + class UsingDirectiveDecl; + +/// DeclarationName - The name of a declaration. In the common case, +/// this just stores an IdentifierInfo pointer to a normal +/// name. However, it also provides encodings for Objective-C +/// selectors (optimizing zero- and one-argument selectors, which make +/// up 78% percent of all selectors in Cocoa.h) and special C++ names +/// for constructors, destructors, and conversion functions. +class DeclarationName { +public: + /// NameKind - The kind of name this object contains. + enum NameKind { + Identifier, + ObjCZeroArgSelector, + ObjCOneArgSelector, + ObjCMultiArgSelector, + CXXConstructorName, + CXXDestructorName, + CXXConversionFunctionName, + CXXOperatorName, + CXXLiteralOperatorName, + CXXUsingDirective + }; + +private: + /// StoredNameKind - The kind of name that is actually stored in the + /// upper bits of the Ptr field. This is only used internally. + enum StoredNameKind { + StoredIdentifier = 0, + StoredObjCZeroArgSelector, + StoredObjCOneArgSelector, + StoredDeclarationNameExtra, + PtrMask = 0x03 + }; + + /// Ptr - The lowest two bits are used to express what kind of name + /// we're actually storing, using the values of NameKind. Depending + /// on the kind of name this is, the upper bits of Ptr may have one + /// of several different meanings: + /// + /// StoredIdentifier - The name is a normal identifier, and Ptr is + /// a normal IdentifierInfo pointer. + /// + /// StoredObjCZeroArgSelector - The name is an Objective-C + /// selector with zero arguments, and Ptr is an IdentifierInfo + /// pointer pointing to the selector name. + /// + /// StoredObjCOneArgSelector - The name is an Objective-C selector + /// with one argument, and Ptr is an IdentifierInfo pointer + /// pointing to the selector name. + /// + /// StoredDeclarationNameExtra - Ptr is actually a pointer to a + /// DeclarationNameExtra structure, whose first value will tell us + /// whether this is an Objective-C selector, C++ operator-id name, + /// or special C++ name. + uintptr_t Ptr; + + /// getStoredNameKind - Return the kind of object that is stored in + /// Ptr. + StoredNameKind getStoredNameKind() const { + return static_cast<StoredNameKind>(Ptr & PtrMask); + } + + /// getExtra - Get the "extra" information associated with this + /// multi-argument selector or C++ special name. + DeclarationNameExtra *getExtra() const { + assert(getStoredNameKind() == StoredDeclarationNameExtra && + "Declaration name does not store an Extra structure"); + return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask); + } + + /// getAsCXXSpecialName - If the stored pointer is actually a + /// CXXSpecialName, returns a pointer to it. Otherwise, returns + /// a NULL pointer. + CXXSpecialName *getAsCXXSpecialName() const { + if (getNameKind() >= CXXConstructorName && + getNameKind() <= CXXConversionFunctionName) + return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); + return 0; + } + + /// getAsCXXOperatorIdName + CXXOperatorIdName *getAsCXXOperatorIdName() const { + if (getNameKind() == CXXOperatorName) + return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask); + return 0; + } + + CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { + if (getNameKind() == CXXLiteralOperatorName) + return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask); + return 0; + } + + // Construct a declaration name from the name of a C++ constructor, + // destructor, or conversion function. + DeclarationName(CXXSpecialName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName"); + Ptr |= StoredDeclarationNameExtra; + } + + // Construct a declaration name from the name of a C++ overloaded + // operator. + DeclarationName(CXXOperatorIdName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId"); + Ptr |= StoredDeclarationNameExtra; + } + + DeclarationName(CXXLiteralOperatorIdName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId"); + Ptr |= StoredDeclarationNameExtra; + } + + /// Construct a declaration name from a raw pointer. + DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { } + + friend class DeclarationNameTable; + friend class NamedDecl; + + /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer + /// for this name as a void pointer. + void *getFETokenInfoAsVoid() const; + +public: + /// DeclarationName - Used to create an empty selector. + DeclarationName() : Ptr(0) { } + + // Construct a declaration name from an IdentifierInfo *. + DeclarationName(const IdentifierInfo *II) + : Ptr(reinterpret_cast<uintptr_t>(II)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); + } + + // Construct a declaration name from an Objective-C selector. + DeclarationName(Selector Sel); + + /// getUsingDirectiveName - Return name for all using-directives. + static DeclarationName getUsingDirectiveName(); + + // operator bool() - Evaluates true when this declaration name is + // non-empty. + operator bool() const { + return ((Ptr & PtrMask) != 0) || + (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask)); + } + + /// Predicate functions for querying what type of name this is. + bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } + bool isObjCZeroArgSelector() const { + return getStoredNameKind() == StoredObjCZeroArgSelector; + } + bool isObjCOneArgSelector() const { + return getStoredNameKind() == StoredObjCOneArgSelector; + } + + /// getNameKind - Determine what kind of name this is. + NameKind getNameKind() const; + + /// \brief Determines whether the name itself is dependent, e.g., because it + /// involves a C++ type that is itself dependent. + /// + /// Note that this does not capture all of the notions of "dependent name", + /// because an identifier can be a dependent name if it is used as the + /// callee in a call expression with dependent arguments. + bool isDependentName() const; + + /// getNameAsString - Retrieve the human-readable string for this name. + std::string getAsString() const; + + /// printName - Print the human-readable name to a stream. + void printName(llvm::raw_ostream &OS) const; + + /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in + /// this declaration name, or NULL if this declaration name isn't a + /// simple identifier. + IdentifierInfo *getAsIdentifierInfo() const { + if (isIdentifier()) + return reinterpret_cast<IdentifierInfo *>(Ptr); + return 0; + } + + /// getAsOpaqueInteger - Get the representation of this declaration + /// name as an opaque integer. + uintptr_t getAsOpaqueInteger() const { return Ptr; } + + /// getAsOpaquePtr - Get the representation of this declaration name as + /// an opaque pointer. + void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); } + + static DeclarationName getFromOpaquePtr(void *P) { + DeclarationName N; + N.Ptr = reinterpret_cast<uintptr_t> (P); + return N; + } + + static DeclarationName getFromOpaqueInteger(uintptr_t P) { + DeclarationName N; + N.Ptr = P; + return N; + } + + /// getCXXNameType - If this name is one of the C++ names (of a + /// constructor, destructor, or conversion function), return the + /// type associated with that name. + QualType getCXXNameType() const; + + /// getCXXOverloadedOperator - If this name is the name of an + /// overloadable operator in C++ (e.g., @c operator+), retrieve the + /// kind of overloaded operator. + OverloadedOperatorKind getCXXOverloadedOperator() const; + + /// getCXXLiteralIdentifier - If this name is the name of a literal + /// operator, retrieve the identifier associated with it. + IdentifierInfo *getCXXLiteralIdentifier() const; + + /// getObjCSelector - Get the Objective-C selector stored in this + /// declaration name. + Selector getObjCSelector() const; + + /// getFETokenInfo/setFETokenInfo - The language front-end is + /// allowed to associate arbitrary metadata with some kinds of + /// declaration names, including normal identifiers and C++ + /// constructors, destructors, and conversion functions. + template<typename T> + T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); } + + void setFETokenInfo(void *T); + + /// operator== - Determine whether the specified names are identical.. + friend bool operator==(DeclarationName LHS, DeclarationName RHS) { + return LHS.Ptr == RHS.Ptr; + } + + /// operator!= - Determine whether the specified names are different. + friend bool operator!=(DeclarationName LHS, DeclarationName RHS) { + return LHS.Ptr != RHS.Ptr; + } + + static DeclarationName getEmptyMarker() { + return DeclarationName(uintptr_t(-1)); + } + + static DeclarationName getTombstoneMarker() { + return DeclarationName(uintptr_t(-2)); + } + + static int compare(DeclarationName LHS, DeclarationName RHS); + + void dump() const; +}; + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator<(DeclarationName LHS, DeclarationName RHS) { + return DeclarationName::compare(LHS, RHS) < 0; +} + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator>(DeclarationName LHS, DeclarationName RHS) { + return DeclarationName::compare(LHS, RHS) > 0; +} + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator<=(DeclarationName LHS, DeclarationName RHS) { + return DeclarationName::compare(LHS, RHS) <= 0; +} + +/// Ordering on two declaration names. If both names are identifiers, +/// this provides a lexicographical ordering. +inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { + return DeclarationName::compare(LHS, RHS) >= 0; +} + +/// DeclarationNameTable - Used to store and retrieve DeclarationName +/// instances for the various kinds of declaration names, e.g., normal +/// identifiers, C++ constructor names, etc. This class contains +/// uniqued versions of each of the C++ special names, which can be +/// retrieved using its member functions (e.g., +/// getCXXConstructorName). +class DeclarationNameTable { + ASTContext &Ctx; + void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * + CXXOperatorIdName *CXXOperatorNames; // Operator names + void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* + + DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE + DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE + +public: + DeclarationNameTable(ASTContext &C); + ~DeclarationNameTable(); + + /// getIdentifier - Create a declaration name that is a simple + /// identifier. + DeclarationName getIdentifier(const IdentifierInfo *ID) { + return DeclarationName(ID); + } + + /// getCXXConstructorName - Returns the name of a C++ constructor + /// for the given Type. + DeclarationName getCXXConstructorName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXConstructorName, + Ty.getUnqualifiedType()); + } + + /// getCXXDestructorName - Returns the name of a C++ destructor + /// for the given Type. + DeclarationName getCXXDestructorName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXDestructorName, + Ty.getUnqualifiedType()); + } + + /// getCXXConversionFunctionName - Returns the name of a C++ + /// conversion function for the given Type. + DeclarationName getCXXConversionFunctionName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); + } + + /// getCXXSpecialName - Returns a declaration name for special kind + /// of C++ name, e.g., for a constructor, destructor, or conversion + /// function. + DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, + CanQualType Ty); + + /// getCXXOperatorName - Get the name of the overloadable C++ + /// operator corresponding to Op. + DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); + + /// getCXXLiteralOperatorName - Get the name of the literal operator function + /// with II as the identifier. + DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); +}; + +/// Insertion operator for diagnostics. This allows sending DeclarationName's +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + DeclarationName N) { + DB.AddTaggedVal(N.getAsOpaqueInteger(), + Diagnostic::ak_declarationname); + return DB; +} + +/// Insertion operator for partial diagnostics. This allows binding +/// DeclarationName's into a partial diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + DeclarationName N) { + PD.AddTaggedVal(N.getAsOpaqueInteger(), + Diagnostic::ak_declarationname); + return PD; +} + +} // end namespace clang + +namespace llvm { +/// Define DenseMapInfo so that DeclarationNames can be used as keys +/// in DenseMap and DenseSets. +template<> +struct DenseMapInfo<clang::DeclarationName> { + static inline clang::DeclarationName getEmptyKey() { + return clang::DeclarationName::getEmptyMarker(); + } + + static inline clang::DeclarationName getTombstoneKey() { + return clang::DeclarationName::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::DeclarationName); + + static inline bool + isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { + return LHS == RHS; + } +}; + +template <> +struct isPodLike<clang::DeclarationName> { static const bool value = true; }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h new file mode 100644 index 0000000..2bbe502 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h @@ -0,0 +1,192 @@ +//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- 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 interfaces for diagnostics which may or may +// fire based on how a template is instantiated. +// +// At the moment, the only consumer of this interface is access +// control. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H +#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H + +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclContextInternals.h" +#include "clang/AST/Type.h" + +namespace clang { + +class ASTContext; +class CXXRecordDecl; +class NamedDecl; + +/// A dependently-generated diagnostic. +class DependentDiagnostic { +public: + enum AccessNonce { Access = 0 }; + + static DependentDiagnostic *Create(ASTContext &Context, + DeclContext *Parent, + AccessNonce _, + SourceLocation Loc, + bool IsMemberAccess, + AccessSpecifier AS, + NamedDecl *TargetDecl, + CXXRecordDecl *NamingClass, + QualType BaseObjectType, + const PartialDiagnostic &PDiag) { + DependentDiagnostic *DD = Create(Context, Parent, PDiag); + DD->AccessData.Loc = Loc.getRawEncoding(); + DD->AccessData.IsMember = IsMemberAccess; + DD->AccessData.Access = AS; + DD->AccessData.TargetDecl = TargetDecl; + DD->AccessData.NamingClass = NamingClass; + DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr(); + return DD; + } + + unsigned getKind() const { + return Access; + } + + bool isAccessToMember() const { + assert(getKind() == Access); + return AccessData.IsMember; + } + + AccessSpecifier getAccess() const { + assert(getKind() == Access); + return AccessSpecifier(AccessData.Access); + } + + SourceLocation getAccessLoc() const { + assert(getKind() == Access); + return SourceLocation::getFromRawEncoding(AccessData.Loc); + } + + NamedDecl *getAccessTarget() const { + assert(getKind() == Access); + return AccessData.TargetDecl; + } + + NamedDecl *getAccessNamingClass() const { + assert(getKind() == Access); + return AccessData.NamingClass; + } + + QualType getAccessBaseObjectType() const { + assert(getKind() == Access); + return QualType::getFromOpaquePtr(AccessData.BaseObjectType); + } + + const PartialDiagnostic &getDiagnostic() const { + return Diag; + } + +private: + DependentDiagnostic(const PartialDiagnostic &PDiag, + PartialDiagnostic::Storage *Storage) + : Diag(PDiag, Storage) {} + + static DependentDiagnostic *Create(ASTContext &Context, + DeclContext *Parent, + const PartialDiagnostic &PDiag); + + friend class DependentStoredDeclsMap; + friend class DeclContext::ddiag_iterator; + DependentDiagnostic *NextDiagnostic; + + PartialDiagnostic Diag; + + union { + struct { + unsigned Loc; + unsigned Access : 2; + unsigned IsMember : 1; + NamedDecl *TargetDecl; + CXXRecordDecl *NamingClass; + void *BaseObjectType; + } AccessData; + }; +}; + +/// + +/// An iterator over the dependent diagnostics in a dependent context. +class DeclContext::ddiag_iterator { +public: + ddiag_iterator() : Ptr(0) {} + explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} + + typedef DependentDiagnostic *value_type; + typedef DependentDiagnostic *reference; + typedef DependentDiagnostic *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + reference operator*() const { return Ptr; } + + ddiag_iterator &operator++() { + assert(Ptr && "attempt to increment past end of diag list"); + Ptr = Ptr->NextDiagnostic; + return *this; + } + + ddiag_iterator operator++(int) { + ddiag_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(ddiag_iterator Other) const { + return Ptr == Other.Ptr; + } + + bool operator!=(ddiag_iterator Other) const { + return Ptr != Other.Ptr; + } + + ddiag_iterator &operator+=(difference_type N) { + assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); + while (N--) + ++*this; + return *this; + } + + ddiag_iterator operator+(difference_type N) const { + ddiag_iterator tmp = *this; + tmp += N; + return tmp; + } + +private: + DependentDiagnostic *Ptr; +}; + +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); + + if (!Map) return ddiag_iterator(); + return ddiag_iterator(Map->FirstDiagnostic); +} + +inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const { + return ddiag_iterator(); +} + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h new file mode 100644 index 0000000..66639e2 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h @@ -0,0 +1,3347 @@ +//===--- Expr.h - Classes for representing expressions ----------*- 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 Expr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPR_H +#define LLVM_CLANG_AST_EXPR_H + +#include "clang/AST/APValue.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/ASTVector.h" +#include "clang/AST/UsuallyTinyPtrVector.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { + class ASTContext; + class APValue; + class Decl; + class IdentifierInfo; + class ParmVarDecl; + class NamedDecl; + class ValueDecl; + class BlockDecl; + class CXXBaseSpecifier; + class CXXOperatorCallExpr; + class CXXMemberCallExpr; + class TemplateArgumentLoc; + class TemplateArgumentListInfo; + +/// \brief A simple array of base specifiers. +typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; + +/// Expr - This represents one expression. Note that Expr's are subclasses of +/// Stmt. This allows an expression to be transparently used any place a Stmt +/// is required. +/// +class Expr : public Stmt { + QualType TR; + + virtual void ANCHOR(); // key function. +protected: + /// TypeDependent - Whether this expression is type-dependent + /// (C++ [temp.dep.expr]). + bool TypeDependent : 1; + + /// ValueDependent - Whether this expression is value-dependent + /// (C++ [temp.dep.constexpr]). + bool ValueDependent : 1; + + Expr(StmtClass SC, QualType T, bool TD, bool VD) + : Stmt(SC), TypeDependent(TD), ValueDependent(VD) { + setType(T); + } + + /// \brief Construct an empty expression. + explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } + +public: + /// \brief Increases the reference count for this expression. + /// + /// Invoke the Retain() operation when this expression + /// is being shared by another owner. + Expr *Retain() { + Stmt::Retain(); + return this; + } + + QualType getType() const { return TR; } + void setType(QualType t) { + // In C++, the type of an expression is always adjusted so that it + // will not have reference type an expression will never have + // reference type (C++ [expr]p6). Use + // QualType::getNonReferenceType() to retrieve the non-reference + // type. Additionally, inspect Expr::isLvalue to determine whether + // an expression that is adjusted in this manner should be + // considered an lvalue. + assert((t.isNull() || !t->isReferenceType()) && + "Expressions can't have reference type"); + + TR = t; + } + + /// isValueDependent - Determines whether this expression is + /// value-dependent (C++ [temp.dep.constexpr]). For example, the + /// array bound of "Chars" in the following example is + /// value-dependent. + /// @code + /// template<int Size, char (&Chars)[Size]> struct meta_string; + /// @endcode + bool isValueDependent() const { return ValueDependent; } + + /// \brief Set whether this expression is value-dependent or not. + void setValueDependent(bool VD) { ValueDependent = VD; } + + /// isTypeDependent - Determines whether this expression is + /// type-dependent (C++ [temp.dep.expr]), which means that its type + /// could change from one template instantiation to the next. For + /// example, the expressions "x" and "x + y" are type-dependent in + /// the following code, but "y" is not type-dependent: + /// @code + /// template<typename T> + /// void add(T x, int y) { + /// x + y; + /// } + /// @endcode + bool isTypeDependent() const { return TypeDependent; } + + /// \brief Set whether this expression is type-dependent or not. + void setTypeDependent(bool TD) { TypeDependent = TD; } + + /// 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. + virtual SourceRange getSourceRange() const = 0; + + /// getExprLoc - Return the preferred location for the arrow when diagnosing + /// a problem with a generic expression. + virtual SourceLocation getExprLoc() const { return getLocStart(); } + + /// isUnusedResultAWarning - Return true if this immediate expression should + /// be warned about if the result is unused. If so, fill in Loc and Ranges + /// with location to warn on and the source range[s] to report with the + /// warning. + bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, + SourceRange &R2, ASTContext &Ctx) const; + + /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or + /// incomplete type other than void. Nonarray expressions that can be lvalues: + /// - name, where name must be a variable + /// - e[i] + /// - (e), where e must be an lvalue + /// - e.name, where e must be an lvalue + /// - e->name + /// - *e, the type of e cannot be a function type + /// - string-constant + /// - reference type [C++ [expr]] + /// - b ? x : y, where x and y are lvalues of suitable types [C++] + /// + enum isLvalueResult { + LV_Valid, + LV_NotObjectType, + LV_IncompleteVoidType, + LV_DuplicateVectorComponents, + LV_InvalidExpression, + LV_MemberFunction, + LV_SubObjCPropertySetting, + LV_ClassTemporary + }; + isLvalueResult isLvalue(ASTContext &Ctx) const; + + // Same as above, but excluding checks for non-object and void types in C + isLvalueResult isLvalueInternal(ASTContext &Ctx) const; + + /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, + /// does not have an incomplete type, does not have a const-qualified type, + /// and if it is a structure or union, does not have any member (including, + /// recursively, any member or element of all contained aggregates or unions) + /// with a const-qualified type. + /// + /// \param Loc [in] [out] - A source location which *may* be filled + /// in with the location of the expression making this a + /// non-modifiable lvalue, if specified. + enum isModifiableLvalueResult { + MLV_Valid, + MLV_NotObjectType, + MLV_IncompleteVoidType, + MLV_DuplicateVectorComponents, + MLV_InvalidExpression, + MLV_LValueCast, // Specialized form of MLV_InvalidExpression. + MLV_IncompleteType, + MLV_ConstQualified, + MLV_ArrayType, + MLV_NotBlockQualified, + MLV_ReadonlyProperty, + MLV_NoSetterProperty, + MLV_MemberFunction, + MLV_SubObjCPropertySetting, + MLV_ClassTemporary + }; + isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, + SourceLocation *Loc = 0) const; + + /// \brief If this expression refers to a bit-field, retrieve the + /// declaration of that bit-field. + FieldDecl *getBitField(); + + const FieldDecl *getBitField() const { + return const_cast<Expr*>(this)->getBitField(); + } + + /// \brief Returns whether this expression refers to a vector element. + bool refersToVectorElement() const; + + /// 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. + 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) 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; + + /// 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; + + EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(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 { + return HasSideEffects; + } + }; + + /// 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, ASTContext &Ctx) const; + + /// EvaluateAsBooleanCondition - Return true if this is a constant + /// which we we can fold and convert to a boolean condition using + /// any crazy technique that we want to. + bool EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const; + + /// isEvaluatable - Call Evaluate to see if this expression can be constant + /// folded, but discard the result. + bool isEvaluatable(ASTContext &Ctx) const; + + /// HasSideEffects - This routine returns true for all those expressions + /// which must be evaluated each time and must not be optimization away + /// or evaluated at compile time. Example is a function call, volatile + /// variable read. + bool HasSideEffects(ASTContext &Ctx) const; + + /// EvaluateAsInt - Call Evaluate and return the folded integer. This + /// must be called on an expression that constant folds to an integer. + llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const; + + /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue + /// with link time known address. + bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; + + /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. + bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const; + + /// \brief Enumeration used to describe how \c isNullPointerConstant() + /// should cope with value-dependent expressions. + 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 - Return true if this is either an + /// integer constant expression with the value zero, or if this is one that is + /// cast to void*. + bool isNullPointerConstant(ASTContext &Ctx, + NullPointerConstantValueDependence NPC) const; + + /// isOBJCGCCandidate - Return true if this expression may be used in a read/ + /// write barrier. + bool isOBJCGCCandidate(ASTContext &Ctx) const; + + /// 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(); + + /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr + /// or CastExprs, returning their operand. + Expr *IgnoreParenCasts(); + + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any + /// ParenExpr or ImplicitCastExprs, returning their operand. + Expr *IgnoreParenImpCasts(); + + /// 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); + + /// \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 + /// 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 this expression directly creates a + /// temporary object (of class type). + bool isTemporaryObject() const { return getTemporaryObject() != 0; } + + /// \brief If this expression directly creates a temporary object of + /// class type, return the expression that actually constructs that + /// temporary object. + const Expr *getTemporaryObject() const; + + const Expr *IgnoreParens() const { + return const_cast<Expr*>(this)->IgnoreParens(); + } + const Expr *IgnoreParenCasts() const { + return const_cast<Expr*>(this)->IgnoreParenCasts(); + } + const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const { + return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); + } + + static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs); + static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs); + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstExprConstant && + T->getStmtClass() <= lastExprConstant; + } + static bool classof(const Expr *) { return true; } +}; + + +//===----------------------------------------------------------------------===// +// Primary Expressions. +//===----------------------------------------------------------------------===// + +/// \brief Represents the qualifier that may precede a C++ name, e.g., the +/// "std::" in "std::sort". +struct NameQualifier { + /// \brief The nested name specifier. + NestedNameSpecifier *NNS; + + /// \brief The source range covered by the nested name specifier. + SourceRange Range; +}; + +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "<int>" in "sort<int>". +struct ExplicitTemplateArgumentList { + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// \brief Retrieve the template arguments + TemplateArgumentLoc *getTemplateArgs() { + return reinterpret_cast<TemplateArgumentLoc *> (this + 1); + } + + /// \brief Retrieve the template arguments + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); + } + + void initializeFrom(const TemplateArgumentListInfo &List); + void copyInto(TemplateArgumentListInfo &List) const; + static std::size_t sizeFor(const TemplateArgumentListInfo &List); +}; + +/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, +/// enum, etc. +class DeclRefExpr : public Expr { + enum { + // Flag on DecoratedD that specifies when this declaration reference + // expression has a C++ nested-name-specifier. + HasQualifierFlag = 0x01, + // Flag on DecoratedD that specifies when this declaration reference + // expression has an explicit C++ template argument list. + HasExplicitTemplateArgumentListFlag = 0x02 + }; + + // DecoratedD - The declaration that we are referencing, plus two bits to + // indicate whether (1) the declaration's name was explicitly qualified and + // (2) the declaration's name was followed by an explicit template + // argument list. + llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; + + // Loc - The location of the declaration name itself. + SourceLocation Loc; + + /// \brief Retrieve the qualifier that preceded the declaration name, if any. + NameQualifier *getNameQualifier() { + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return 0; + + return reinterpret_cast<NameQualifier *> (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const NameQualifier *getNameQualifier() const { + return const_cast<DeclRefExpr *>(this)->getNameQualifier(); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0) + return 0; + + if ((DecoratedD.getInt() & HasQualifierFlag) == 0) + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return reinterpret_cast<ExplicitTemplateArgumentList *>( + getNameQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList(); + } + + DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + ValueDecl *D, SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs, + QualType T); + +protected: + /// \brief Computes the type- and value-dependence flags for this + /// declaration reference expression. + void computeDependence(); + + DeclRefExpr(StmtClass SC, ValueDecl *d, QualType t, SourceLocation l) : + Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) { + computeDependence(); + } + +public: + DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) : + Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) { + computeDependence(); + } + + /// \brief Construct an empty declaration reference expression. + explicit DeclRefExpr(EmptyShell Empty) + : Expr(DeclRefExprClass, Empty) { } + + static DeclRefExpr *Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + ValueDecl *D, + SourceLocation NameLoc, + QualType T, + const TemplateArgumentListInfo *TemplateArgs = 0); + + ValueDecl *getDecl() { return DecoratedD.getPointer(); } + const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } + void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + virtual SourceRange getSourceRange() const; + + /// \brief Determine whether this declaration reference was preceded by a + /// C++ nested-name-specifier, e.g., \c N::foo. + bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } + + /// \brief If the name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!hasQualifier()) + return SourceRange(); + + return getNameQualifier()->Range; + } + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name. Otherwise, returns NULL. + NestedNameSpecifier *getQualifier() const { + if (!hasQualifier()) + return 0; + + return getNameQualifier()->NNS; + } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() const { + return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; + } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgumentList()) + getExplicitTemplateArgumentList()->copyInto(List); + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgumentList()) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!hasExplicitTemplateArgumentList()) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclRefExprClass; + } + static bool classof(const DeclRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. +class PredefinedExpr : public Expr { +public: + enum IdentType { + Func, + Function, + PrettyFunction, + /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual + }; + +private: + SourceLocation Loc; + IdentType Type; +public: + PredefinedExpr(SourceLocation l, QualType type, IdentType IT) + : Expr(PredefinedExprClass, type, type->isDependentType(), + type->isDependentType()), Loc(l), Type(IT) {} + + /// \brief Construct an empty predefined expression. + explicit PredefinedExpr(EmptyShell Empty) + : Expr(PredefinedExprClass, Empty) { } + + IdentType getIdentType() const { return Type; } + void setIdentType(IdentType IT) { Type = IT; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PredefinedExprClass; + } + static bool classof(const PredefinedExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class IntegerLiteral : public Expr { + llvm::APInt Value; + SourceLocation Loc; +public: + // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, + // or UnsignedLongLongTy + IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) + : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) { + assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); + } + + /// \brief Construct an empty integer literal. + explicit IntegerLiteral(EmptyShell Empty) + : Expr(IntegerLiteralClass, Empty) { } + + const llvm::APInt &getValue() const { return Value; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + /// \brief Retrieve the location of the literal. + SourceLocation getLocation() const { return Loc; } + + void setValue(const llvm::APInt &Val) { Value = Val; } + void setLocation(SourceLocation Location) { Loc = Location; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == IntegerLiteralClass; + } + static bool classof(const IntegerLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class CharacterLiteral : public Expr { + unsigned Value; + SourceLocation Loc; + bool IsWide; +public: + // type should be IntTy + CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l) + : Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l), + IsWide(iswide) { + } + + /// \brief Construct an empty character literal. + CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } + + SourceLocation getLocation() const { return Loc; } + bool isWide() const { return IsWide; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + unsigned getValue() const { return Value; } + + void setLocation(SourceLocation Location) { Loc = Location; } + void setWide(bool W) { IsWide = W; } + void setValue(unsigned Val) { Value = Val; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CharacterLiteralClass; + } + static bool classof(const CharacterLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class FloatingLiteral : public Expr { + llvm::APFloat Value; + bool IsExact : 1; + SourceLocation Loc; +public: + FloatingLiteral(const llvm::APFloat &V, bool isexact, + QualType Type, SourceLocation L) + : Expr(FloatingLiteralClass, Type, false, false), Value(V), + IsExact(isexact), Loc(L) {} + + /// \brief Construct an empty floating-point literal. + explicit FloatingLiteral(EmptyShell Empty) + : Expr(FloatingLiteralClass, Empty), Value(0.0) { } + + const llvm::APFloat &getValue() const { return Value; } + void setValue(const llvm::APFloat &Val) { Value = Val; } + + bool isExact() const { return IsExact; } + void setExact(bool E) { IsExact = E; } + + /// getValueAsApproximateDouble - This returns the value as an inaccurate + /// double. Note that this may cause loss of precision, but is useful for + /// debugging dumps, etc. + double getValueAsApproximateDouble() const; + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == FloatingLiteralClass; + } + static bool classof(const FloatingLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ImaginaryLiteral - We support imaginary integer and floating point literals, +/// like "1.0i". We represent these as a wrapper around FloatingLiteral and +/// IntegerLiteral classes. Instances of this class always have a Complex type +/// whose element type matches the subexpression. +/// +class ImaginaryLiteral : public Expr { + Stmt *Val; +public: + ImaginaryLiteral(Expr *val, QualType Ty) + : Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {} + + /// \brief Build an empty imaginary literal. + explicit ImaginaryLiteral(EmptyShell Empty) + : Expr(ImaginaryLiteralClass, Empty) { } + + const Expr *getSubExpr() const { return cast<Expr>(Val); } + Expr *getSubExpr() { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + virtual SourceRange getSourceRange() const { return Val->getSourceRange(); } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImaginaryLiteralClass; + } + static bool classof(const ImaginaryLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// StringLiteral - This represents a string literal expression, e.g. "foo" +/// or L"bar" (wide strings). The actual string is returned by getStrData() +/// is NOT null-terminated, and the length of the string is determined by +/// calling getByteLength(). The C type for a string is always a +/// ConstantArrayType. In C++, the char type is const qualified, in C it is +/// not. +/// +/// Note that strings in C can be formed by concatenation of multiple string +/// literal pptokens in translation phase #6. This keeps track of the locations +/// of each of these pieces. +/// +/// Strings in C can also be truncated and extended by assigning into arrays, +/// e.g. with constructs like: +/// char X[2] = "foobar"; +/// In this case, getByteLength() will return 6, but the string literal will +/// have type "char[2]". +class StringLiteral : public Expr { + const char *StrData; + unsigned ByteLength; + bool IsWide; + unsigned NumConcatenated; + SourceLocation TokLocs[1]; + + StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {} + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + /// This is the "fully general" constructor that allows representation of + /// strings formed from multiple concatenated tokens. + static StringLiteral *Create(ASTContext &C, const char *StrData, + unsigned ByteLength, bool Wide, QualType Ty, + const SourceLocation *Loc, unsigned NumStrs); + + /// Simple constructor for string literals made from one token. + static StringLiteral *Create(ASTContext &C, const char *StrData, + unsigned ByteLength, + bool Wide, QualType Ty, SourceLocation Loc) { + return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1); + } + + /// \brief Construct an empty string literal. + static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); + + llvm::StringRef getString() const { + return llvm::StringRef(StrData, ByteLength); + } + // FIXME: These are deprecated, replace with StringRef. + const char *getStrData() const { return StrData; } + unsigned getByteLength() const { return ByteLength; } + + /// \brief Sets the string data to the given string data. + void setString(ASTContext &C, llvm::StringRef Str); + + bool isWide() const { return IsWide; } + void setWide(bool W) { IsWide = W; } + + bool containsNonAsciiOrNull() const { + llvm::StringRef Str = getString(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isascii(Str[i]) || !Str[i]) + 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; } + + SourceLocation getStrTokenLoc(unsigned TokNum) const { + assert(TokNum < NumConcatenated && "Invalid tok number"); + return TokLocs[TokNum]; + } + void setStrTokenLoc(unsigned TokNum, SourceLocation L) { + assert(TokNum < NumConcatenated && "Invalid tok number"); + TokLocs[TokNum] = L; + } + + typedef const SourceLocation *tokloc_iterator; + tokloc_iterator tokloc_begin() const { return TokLocs; } + tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } + + virtual SourceRange getSourceRange() const { + return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == StringLiteralClass; + } + static bool classof(const StringLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This +/// AST node is only formed if full location information is requested. +class ParenExpr : public Expr { + SourceLocation L, R; + Stmt *Val; +public: + ParenExpr(SourceLocation l, SourceLocation r, Expr *val) + : Expr(ParenExprClass, val->getType(), + val->isTypeDependent(), val->isValueDependent()), + L(l), R(r), Val(val) {} + + /// \brief Construct an empty parenthesized expression. + explicit ParenExpr(EmptyShell Empty) + : Expr(ParenExprClass, Empty) { } + + const Expr *getSubExpr() const { return cast<Expr>(Val); } + Expr *getSubExpr() { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + virtual SourceRange getSourceRange() const { return SourceRange(L, R); } + + /// \brief Get the location of the left parentheses '('. + SourceLocation getLParen() const { return L; } + void setLParen(SourceLocation Loc) { L = Loc; } + + /// \brief Get the location of the right parentheses ')'. + SourceLocation getRParen() const { return R; } + void setRParen(SourceLocation Loc) { R = Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenExprClass; + } + static bool classof(const ParenExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// UnaryOperator - This represents the unary-expression's (except sizeof and +/// alignof), the postinc/postdec operators from postfix-expression, and various +/// extensions. +/// +/// Notes on various nodes: +/// +/// Real/Imag - These return the real/imag part of a complex operand. If +/// applied to a non-complex value, the former returns its operand and the +/// later returns zero in the type of the operand. +/// +/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose +/// subexpression is a compound literal with the various MemberExpr and +/// ArraySubscriptExpr's applied to it. (This is only used in C) +/// +class UnaryOperator : public Expr { +public: + // Note that additions to this should also update the StmtVisitor class. + enum Opcode { + PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators + PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators. + AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators. + Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators. + Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators. + Real, Imag, // "__real expr"/"__imag expr" Extension. + Extension, // __extension__ marker. + OffsetOf // __builtin_offsetof + }; +private: + Stmt *Val; + Opcode Opc; + SourceLocation Loc; +public: + + UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) + : Expr(UnaryOperatorClass, type, + input->isTypeDependent() && opc != OffsetOf, + input->isValueDependent()), + Val(input), Opc(opc), Loc(l) {} + + /// \brief Build an empty unary operator. + explicit UnaryOperator(EmptyShell Empty) + : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { } + + Opcode getOpcode() const { return Opc; } + void setOpcode(Opcode O) { Opc = O; } + + Expr *getSubExpr() const { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return Loc; } + void setOperatorLoc(SourceLocation L) { Loc = L; } + + /// isPostfix - Return true if this is a postfix operation, like x++. + static bool isPostfix(Opcode Op) { + return Op == PostInc || Op == PostDec; + } + + /// isPostfix - Return true if this is a prefix operation, like --x. + static bool isPrefix(Opcode Op) { + return Op == PreInc || Op == PreDec; + } + + bool isPrefix() const { return isPrefix(Opc); } + bool isPostfix() const { return isPostfix(Opc); } + bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; } + bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } + bool isOffsetOfOp() const { return Opc == OffsetOf; } + static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } + bool isArithmeticOp() const { return isArithmeticOp(Opc); } + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it + /// corresponds to, e.g. "sizeof" or "[pre]++" + static const char *getOpcodeStr(Opcode Op); + + /// \brief Retrieve the unary opcode that corresponds to the given + /// overloaded operator. + static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); + + /// \brief Retrieve the overloaded operator kind that corresponds to + /// the given unary opcode. + static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); + + virtual SourceRange getSourceRange() const { + if (isPostfix()) + return SourceRange(Val->getLocStart(), Loc); + else + return SourceRange(Loc, Val->getLocEnd()); + } + virtual SourceLocation getExprLoc() const { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnaryOperatorClass; + } + static bool classof(const UnaryOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form +/// offsetof(record-type, member-designator). For example, given: +/// @code +/// struct S { +/// float f; +/// 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). + +class OffsetOfExpr : public Expr { +public: + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + class OffsetOfNode { + public: + /// \brief The kind of offsetof node we have. + enum Kind { + /// \brief An index into an array. + Array = 0x00, + /// \brief A field. + Field = 0x01, + /// \brief A field in a dependent type, known only by its name. + Identifier = 0x02, + /// \brief An implicit indirection through a C++ base class, when the + /// field found is in a base class. + Base = 0x03 + }; + + 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 + /// 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 + /// base class. + uintptr_t Data; + + public: + /// \brief Create an offsetof node that refers to an array element. + 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, + SourceLocation 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), + 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 { + return static_cast<Kind>(Data & Mask); + } + + /// \brief For an array element node, returns the index into the array + /// of expressions. + unsigned getArrayExprIndex() const { + assert(getKind() == Array); + return Data >> 2; + } + + /// \brief For a field offsetof node, returns the field. + FieldDecl *getField() const { + 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); + } + + /// \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 + /// identifier. + SourceRange getRange() const { return Range; } + }; + +private: + + SourceLocation OperatorLoc, RParenLoc; + // Base type; + TypeSourceInfo *TSInfo; + // Number of sub-components (i.e. instances of OffsetOfNode). + unsigned NumComps; + // Number of sub-expressions (i.e. array subscript expressions). + unsigned NumExprs; + + OffsetOfExpr(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + 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) {} + +public: + + 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, + unsigned NumComps, unsigned NumExprs); + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \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) { + assert(Idx < NumComps && "Subscript out of range"); + return reinterpret_cast<OffsetOfNode *> (this + 1)[Idx]; + } + + void setComponent(unsigned Idx, OffsetOfNode ON) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; + } + + unsigned getNumComponents() const { + return NumComps; + } + + Expr* getIndexExpr(unsigned Idx) { + assert(Idx < NumExprs && "Subscript out of range"); + return reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx]; + } + + void setIndexExpr(unsigned Idx, Expr* E) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; + } + + unsigned getNumExpressions() const { + return NumExprs; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(OperatorLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OffsetOfExprClass; + } + + static bool classof(const OffsetOfExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of +/// types and expressions. +class SizeOfAlignOfExpr : public Expr { + bool isSizeof : 1; // true if sizeof, false if alignof. + bool isType : 1; // true if operand is a type, false if an expression + union { + TypeSourceInfo *Ty; + Stmt *Ex; + } Argument; + SourceLocation OpLoc, RParenLoc; + +protected: + virtual void DoDestroy(ASTContext& C); + +public: + SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(SizeOfAlignOfExprClass, resultType, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + TInfo->getType()->isDependentType()), + isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { + Argument.Ty = TInfo; + } + + SizeOfAlignOfExpr(bool issizeof, Expr *E, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(SizeOfAlignOfExprClass, resultType, + false, // Never type-dependent (C++ [temp.dep.expr]p3). + // Value-dependent if the argument is type-dependent. + E->isTypeDependent()), + isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { + Argument.Ex = E; + } + + /// \brief Construct an empty sizeof/alignof expression. + explicit SizeOfAlignOfExpr(EmptyShell Empty) + : Expr(SizeOfAlignOfExprClass, Empty) { } + + bool isSizeOf() const { return isSizeof; } + void setSizeof(bool S) { isSizeof = S; } + + bool isArgumentType() const { return isType; } + QualType getArgumentType() const { + return getArgumentTypeInfo()->getType(); + } + TypeSourceInfo *getArgumentTypeInfo() const { + assert(isArgumentType() && "calling getArgumentType() when arg is expr"); + return Argument.Ty; + } + Expr *getArgumentExpr() { + assert(!isArgumentType() && "calling getArgumentExpr() when arg is type"); + return static_cast<Expr*>(Argument.Ex); + } + const Expr *getArgumentExpr() const { + return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr(); + } + + void setArgument(Expr *E) { Argument.Ex = E; isType = false; } + void setArgument(TypeSourceInfo *TInfo) { + Argument.Ty = TInfo; + isType = true; + } + + /// Gets the argument type, or the type of the argument expression, whichever + /// is appropriate. + QualType getTypeOfArgument() const { + return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType(); + } + + SourceLocation getOperatorLoc() const { return OpLoc; } + void setOperatorLoc(SourceLocation L) { OpLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(OpLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SizeOfAlignOfExprClass; + } + static bool classof(const SizeOfAlignOfExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +//===----------------------------------------------------------------------===// +// Postfix Operators. +//===----------------------------------------------------------------------===// + +/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. +class ArraySubscriptExpr : public Expr { + enum { LHS, RHS, END_EXPR=2 }; + Stmt* SubExprs[END_EXPR]; + SourceLocation RBracketLoc; +public: + ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, + SourceLocation rbracketloc) + : Expr(ArraySubscriptExprClass, t, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + RBracketLoc(rbracketloc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + /// \brief Create an empty array subscript expression. + explicit ArraySubscriptExpr(EmptyShell Shell) + : Expr(ArraySubscriptExprClass, Shell) { } + + /// An array access can be written A[4] or 4[A] (both are equivalent). + /// - getBase() and getIdx() always present the normalized view: A[4]. + /// In this case getBase() returns "A" and getIdx() returns "4". + /// - getLHS() and getRHS() present the syntactic view. e.g. for + /// 4[A] getLHS() returns "4". + /// Note: Because vector element access is also written A[4] we must + /// predicate the format conversion in getBase and getIdx only on the + /// the type of the RHS, as it is possible for the LHS to be a vector of + /// integer type + Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); } + const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } + void setLHS(Expr *E) { SubExprs[LHS] = E; } + + Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); } + const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } + void setRHS(Expr *E) { SubExprs[RHS] = E; } + + Expr *getBase() { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + } + + const Expr *getBase() const { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + } + + Expr *getIdx() { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); + } + + const Expr *getIdx() const { + return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(getLHS()->getLocStart(), RBracketLoc); + } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + virtual SourceLocation getExprLoc() const { return getBase()->getExprLoc(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArraySubscriptExprClass; + } + static bool classof(const ArraySubscriptExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). +/// CallExpr itself represents a normal function call, e.g., "f(x, 2)", +/// while its subclasses may represent alternative syntax that (semantically) +/// results in a function call. For example, CXXOperatorCallExpr is +/// a subclass for overloaded operator calls that use operator syntax, e.g., +/// "str1 + str2" to resolve to a function call. +class CallExpr : public Expr { + enum { FN=0, ARGS_START=1 }; + Stmt **SubExprs; + unsigned NumArgs; + SourceLocation RParenLoc; + +protected: + // This version of the constructor is for derived classes. + CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs, + QualType t, SourceLocation rparenloc); + + virtual void DoDestroy(ASTContext& C); + +public: + CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, + SourceLocation rparenloc); + + /// \brief Build an empty call expression. + CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); + + ~CallExpr() {} + + const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } + Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } + void setCallee(Expr *F) { SubExprs[FN] = F; } + + Decl *getCalleeDecl(); + const Decl *getCalleeDecl() const { + return const_cast<CallExpr*>(this)->getCalleeDecl(); + } + + /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. + FunctionDecl *getDirectCallee(); + const FunctionDecl *getDirectCallee() const { + return const_cast<CallExpr*>(this)->getDirectCallee(); + } + + /// getNumArgs - Return the number of actual arguments to this call. + /// + unsigned getNumArgs() const { return NumArgs; } + + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(SubExprs[Arg+ARGS_START]); + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(SubExprs[Arg+ARGS_START]); + } + + /// setArg - Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < NumArgs && "Arg access out of range!"); + SubExprs[Arg+ARGS_START] = ArgExpr; + } + + /// setNumArgs - This changes the number of arguments present in this call. + /// Any orphaned expressions are deleted by this, and any new operands are set + /// to null. + void setNumArgs(ASTContext& C, unsigned NumArgs); + + typedef ExprIterator arg_iterator; + typedef ConstExprIterator const_arg_iterator; + + arg_iterator arg_begin() { return SubExprs+ARGS_START; } + arg_iterator arg_end() { return SubExprs+ARGS_START+getNumArgs(); } + const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; } + const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();} + + /// getNumCommas - Return the number of commas that must have been present in + /// this function call. + unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } + + /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If + /// not, return 0. + unsigned isBuiltinCall(ASTContext &Context) 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 + /// type. + QualType getCallReturnType() const; + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCallee()->getLocStart(), RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstCallExprConstant && + T->getStmtClass() <= lastCallExprConstant; + } + static bool classof(const CallExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. +/// +class MemberExpr : public Expr { + /// Extra data stored in some member expressions. + struct MemberNameQualifier : public NameQualifier { + DeclAccessPair FoundDecl; + }; + + /// Base - the expression for the base pointer or structure references. In + /// X.F, this is "X". + Stmt *Base; + + /// MemberDecl - This is the decl being referenced by the field/member name. + /// In X.F, this is the decl referenced by F. + ValueDecl *MemberDecl; + + /// 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; + + /// \brief True if this member expression used a nested-name-specifier to + /// refer to the member, e.g., "x->Base::f", or found its member via a using + /// declaration. When true, a MemberNameQualifier + /// 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 Retrieve the qualifier that preceded the member name, if any. + MemberNameQualifier *getMemberQualifier() { + assert(HasQualifierOrFoundDecl); + return reinterpret_cast<MemberNameQualifier *> (this + 1); + } + + /// \brief Retrieve the qualifier that preceded the member name, if any. + const MemberNameQualifier *getMemberQualifier() const { + return const_cast<MemberExpr *>(this)->getMemberQualifier(); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + if (!HasExplicitTemplateArgumentList) + return 0; + + if (!HasQualifierOrFoundDecl) + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + + return reinterpret_cast<ExplicitTemplateArgumentList *>( + getMemberQualifier() + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList(); + } + +public: + MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, + SourceLocation l, QualType ty) + : Expr(MemberExprClass, ty, + base->isTypeDependent(), base->isValueDependent()), + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} + + /// \brief Build an empty member reference expression. + explicit MemberExpr(EmptyShell Empty) + : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false), + HasExplicitTemplateArgumentList(false) { } + + static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, + NestedNameSpecifier *qual, SourceRange qualrange, + ValueDecl *memberdecl, DeclAccessPair founddecl, + SourceLocation l, + const TemplateArgumentListInfo *targs, + QualType ty); + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + /// \brief Retrieve the member declaration to which this expression refers. + /// + /// The returned declaration will either be a FieldDecl or (in C++) + /// a CXXMethodDecl. + ValueDecl *getMemberDecl() const { return MemberDecl; } + void setMemberDecl(ValueDecl *D) { MemberDecl = D; } + + /// \brief Retrieves the declaration found by lookup. + DeclAccessPair getFoundDecl() const { + if (!HasQualifierOrFoundDecl) + return DeclAccessPair::make(getMemberDecl(), + getMemberDecl()->getAccess()); + return getMemberQualifier()->FoundDecl; + } + + /// \brief Determines whether this member expression actually had + /// a C++ nested-name-specifier prior to the name of the member, e.g., + /// x->Base::foo. + bool hasQualifier() const { return getQualifier() != 0; } + + /// \brief If the member name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the member name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { + if (!HasQualifierOrFoundDecl) + return SourceRange(); + + return getMemberQualifier()->Range; + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { + if (!HasQualifierOrFoundDecl) + return 0; + + return getMemberQualifier()->NNS; + } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgumentList() const { + return HasExplicitTemplateArgumentList; + } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgumentList()) + getExplicitTemplateArgumentList()->copyInto(List); + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!HasExplicitTemplateArgumentList) + return 0; + + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + if (!HasExplicitTemplateArgumentList) + return SourceLocation(); + + return getExplicitTemplateArgumentList()->RAngleLoc; + } + + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// getMemberLoc - Return the location of the "member", in X->F, it is the + /// location of 'F'. + SourceLocation getMemberLoc() const { return MemberLoc; } + void setMemberLoc(SourceLocation L) { MemberLoc = L; } + + virtual SourceRange getSourceRange() const { + // If we have an implicit base (like a C++ implicit this), + // make sure not to return its location + SourceLocation EndLoc = MemberLoc; + if (HasExplicitTemplateArgumentList) + EndLoc = getRAngleLoc(); + + SourceLocation BaseLoc = getBase()->getLocStart(); + if (BaseLoc.isInvalid()) + return SourceRange(MemberLoc, EndLoc); + return SourceRange(BaseLoc, EndLoc); + } + + virtual SourceLocation getExprLoc() const { return MemberLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MemberExprClass; + } + static bool classof(const MemberExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CompoundLiteralExpr - [C99 6.5.2.5] +/// +class CompoundLiteralExpr : public Expr { + /// LParenLoc - If non-null, this is the location of the left paren in a + /// compound literal like "(int){4}". This can be null if this is a + /// synthesized compound expression. + SourceLocation LParenLoc; + + /// The type as written. This can be an incomplete array type, in + /// which case the actual expression type will be different. + TypeSourceInfo *TInfo; + Stmt *Init; + bool FileScope; +public: + // FIXME: Can compound literals be value-dependent? + CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, + QualType T, Expr *init, bool fileScope) + : Expr(CompoundLiteralExprClass, T, + tinfo->getType()->isDependentType(), false), + LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {} + + /// \brief Construct an empty compound literal. + explicit CompoundLiteralExpr(EmptyShell Empty) + : Expr(CompoundLiteralExprClass, Empty) { } + + const Expr *getInitializer() const { return cast<Expr>(Init); } + Expr *getInitializer() { return cast<Expr>(Init); } + void setInitializer(Expr *E) { Init = E; } + + bool isFileScope() const { return FileScope; } + void setFileScope(bool FS) { FileScope = FS; } + + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } + void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; } + + virtual SourceRange getSourceRange() const { + // FIXME: Init should never be null. + if (!Init) + return SourceRange(); + if (LParenLoc.isInvalid()) + return Init->getSourceRange(); + return SourceRange(LParenLoc, Init->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CompoundLiteralExprClass; + } + static bool classof(const CompoundLiteralExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CastExpr - Base class for type casts, including both implicit +/// casts (ImplicitCastExpr) and explicit casts that have some +/// representation in the source code (ExplicitCastExpr's derived +/// classes). +class CastExpr : public Expr { +public: + /// CastKind - the kind of cast this represents. + enum CastKind { + /// CK_Unknown - Unknown cast kind. + /// FIXME: The goal is to get rid of this and make all casts have a + /// kind so that the AST client doesn't have to try to figure out what's + /// going on. + CK_Unknown, + + /// CK_BitCast - Used for reinterpret_cast. + CK_BitCast, + + /// CK_NoOp - Used for const_cast. + CK_NoOp, + + /// CK_BaseToDerived - Base to derived class casts. + CK_BaseToDerived, + + /// CK_DerivedToBase - Derived to base class casts. + CK_DerivedToBase, + + /// CK_UncheckedDerivedToBase - Derived to base class casts that + /// assume that the derived pointer is not null. + CK_UncheckedDerivedToBase, + + /// CK_Dynamic - Dynamic cast. + CK_Dynamic, + + /// CK_ToUnion - Cast to union (GCC extension). + CK_ToUnion, + + /// CK_ArrayToPointerDecay - Array to pointer decay. + CK_ArrayToPointerDecay, + + // CK_FunctionToPointerDecay - Function to pointer decay. + CK_FunctionToPointerDecay, + + /// CK_NullToMemberPointer - Null pointer to member pointer. + CK_NullToMemberPointer, + + /// CK_BaseToDerivedMemberPointer - Member pointer in base class to + /// member pointer in derived class. + CK_BaseToDerivedMemberPointer, + + /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to + /// member pointer in base class. + CK_DerivedToBaseMemberPointer, + + /// CK_UserDefinedConversion - Conversion using a user defined type + /// conversion function. + CK_UserDefinedConversion, + + /// CK_ConstructorConversion - Conversion by constructor + CK_ConstructorConversion, + + /// CK_IntegralToPointer - Integral to pointer + CK_IntegralToPointer, + + /// CK_PointerToIntegral - Pointer to integral + CK_PointerToIntegral, + + /// CK_ToVoid - Cast to void. + CK_ToVoid, + + /// CK_VectorSplat - Casting from an integer/floating type to an extended + /// vector type with the same element type as the src type. Splats the + /// src expression into the destination expression. + CK_VectorSplat, + + /// CK_IntegralCast - Casting between integral types of different size. + CK_IntegralCast, + + /// CK_IntegralToFloating - Integral to floating point. + CK_IntegralToFloating, + + /// CK_FloatingToIntegral - Floating point to integral. + CK_FloatingToIntegral, + + /// CK_FloatingCast - Casting between floating types of different size. + CK_FloatingCast, + + /// CK_MemberPointerToBoolean - Member pointer to boolean + CK_MemberPointerToBoolean, + + /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c + /// pointer + CK_AnyPointerToObjCPointerCast, + /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block + /// pointer + CK_AnyPointerToBlockPointerCast + + }; + +private: + CastKind Kind; + Stmt *Op; + + /// BasePath - For derived-to-base and base-to-derived casts, the base array + /// contains the inheritance path. + CXXBaseSpecifierArray BasePath; + + void CheckBasePath() const { +#ifndef NDEBUG + switch (getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerived: + case CK_BaseToDerivedMemberPointer: + assert(!BasePath.empty() && "Cast kind should have a base path!"); + break; + + // These should not have an inheritance path. + case CK_Unknown: + case CK_BitCast: + case CK_NoOp: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToMemberPointer: + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingCast: + case CK_MemberPointerToBoolean: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + assert(BasePath.empty() && "Cast kind should not have a base path!"); + break; + } +#endif + } + +protected: + CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath) : + Expr(SC, ty, + // Cast expressions are type-dependent if the type is + // dependent (C++ [temp.dep.expr]p3). + ty->isDependentType(), + // Cast expressions are value-dependent if the type is + // dependent or if the subexpression is value-dependent. + ty->isDependentType() || (op && op->isValueDependent())), + Kind(kind), Op(op), BasePath(BasePath) { + CheckBasePath(); + } + + /// \brief Construct an empty cast. + CastExpr(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) { } + + virtual void DoDestroy(ASTContext &C); + +public: + CastKind getCastKind() const { return Kind; } + void setCastKind(CastKind K) { Kind = K; } + const char *getCastKindName() const; + + Expr *getSubExpr() { return cast<Expr>(Op); } + const Expr *getSubExpr() const { return cast<Expr>(Op); } + void setSubExpr(Expr *E) { Op = E; } + + /// \brief Retrieve the cast subexpression as it was written in the source + /// code, looking through any implicit casts or other intermediate nodes + /// introduced by semantic analysis. + Expr *getSubExprAsWritten(); + const Expr *getSubExprAsWritten() const { + return const_cast<CastExpr *>(this)->getSubExprAsWritten(); + } + + const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstCastExprConstant && + T->getStmtClass() <= lastCastExprConstant; + } + static bool classof(const CastExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ImplicitCastExpr - Allows us to explicitly represent implicit type +/// conversions, which have no direct representation in the original +/// source code. For example: converting T[]->T*, void f()->void +/// (*f)(), float->double, short->int, etc. +/// +/// In C, implicit casts always produce rvalues. However, in C++, an +/// implicit cast whose result is being bound to a reference will be +/// an lvalue. For example: +/// +/// @code +/// class Base { }; +/// class Derived : public Base { }; +/// void f(Derived d) { +/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base +/// } +/// @endcode +class ImplicitCastExpr : public CastExpr { + /// LvalueCast - Whether this cast produces an lvalue. + bool LvalueCast; + +public: + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, bool Lvalue) + : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), + LvalueCast(Lvalue) { } + + /// \brief Construct an empty implicit cast. + explicit ImplicitCastExpr(EmptyShell Shell) + : CastExpr(ImplicitCastExprClass, Shell) { } + + virtual SourceRange getSourceRange() const { + return getSubExpr()->getSourceRange(); + } + + /// isLvalueCast - Whether this cast produces an lvalue. + bool isLvalueCast() const { return LvalueCast; } + + /// setLvalueCast - Set whether this cast produces an lvalue. + void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImplicitCastExprClass; + } + static bool classof(const ImplicitCastExpr *) { return true; } +}; + +/// ExplicitCastExpr - An explicit cast written in the source +/// code. +/// +/// This class is effectively an abstract class, because it provides +/// the basic representation of an explicitly-written cast without +/// specifying which kind of cast (C cast, functional cast, static +/// cast, etc.) was written; specific derived classes represent the +/// particular style of cast and its location information. +/// +/// Unlike implicit casts, explicit cast nodes have two different +/// types: the type that was written into the source code, and the +/// actual type of the expression as determined by semantic +/// analysis. These types may differ slightly. For example, in C++ one +/// can cast to a reference type, which indicates that the resulting +/// expression will be an lvalue. The reference type, however, will +/// not be used as the type of the expression. +class ExplicitCastExpr : public CastExpr { + /// TInfo - Source type info for the (written) type + /// this expression is casting to. + TypeSourceInfo *TInfo; + +protected: + ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, + Expr *op, CXXBaseSpecifierArray BasePath, + TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {} + + /// \brief Construct an empty explicit cast. + ExplicitCastExpr(StmtClass SC, EmptyShell Shell) + : CastExpr(SC, Shell) { } + +public: + /// getTypeInfoAsWritten - Returns the type source info for the type + /// that this expression is casting to. + TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; } + void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; } + + /// getTypeAsWritten - Returns the type that this expression is + /// casting to, as written in the source code. + QualType getTypeAsWritten() const { return TInfo->getType(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstExplicitCastExprConstant && + T->getStmtClass() <= lastExplicitCastExprConstant; + } + static bool classof(const ExplicitCastExpr *) { return true; } +}; + +/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style +/// cast in C++ (C++ [expr.cast]), which uses the syntax +/// (Type)expr. For example: @c (int)f. +class CStyleCastExpr : public ExplicitCastExpr { + SourceLocation LPLoc; // the location of the left paren + SourceLocation RPLoc; // the location of the right paren +public: + CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation r) + : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath, + writtenTy), LPLoc(l), RPLoc(r) {} + + /// \brief Construct an empty C-style explicit cast. + explicit CStyleCastExpr(EmptyShell Shell) + : ExplicitCastExpr(CStyleCastExprClass, Shell) { } + + SourceLocation getLParenLoc() const { return LPLoc; } + void setLParenLoc(SourceLocation L) { LPLoc = L; } + + SourceLocation getRParenLoc() const { return RPLoc; } + void setRParenLoc(SourceLocation L) { RPLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CStyleCastExprClass; + } + static bool classof(const CStyleCastExpr *) { return true; } +}; + +/// \brief A builtin binary operation expression such as "x + y" or "x <= y". +/// +/// This expression node kind describes a builtin binary operation, +/// such as "x + y" for integer values "x" and "y". The operands will +/// already have been converted to appropriate types (e.g., by +/// performing promotions or conversions). +/// +/// In C++, where operators may be overloaded, a different kind of +/// expression node (CXXOperatorCallExpr) is used to express the +/// invocation of an overloaded operator with operator syntax. Within +/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is +/// used to store an expression "x + y" depends on the subexpressions +/// for x and y. If neither x or y is type-dependent, and the "+" +/// operator resolves to a built-in operation, BinaryOperator will be +/// used to express the computation (x and y may still be +/// value-dependent). If either x or y is type-dependent, or if the +/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will +/// be used to express the computation. +class BinaryOperator : public Expr { +public: + enum Opcode { + // Operators listed in order of precedence. + // Note that additions to this should also update the StmtVisitor class. + PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators. + Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. + Add, Sub, // [C99 6.5.6] Additive operators. + Shl, Shr, // [C99 6.5.7] Bitwise shift operators. + LT, GT, LE, GE, // [C99 6.5.8] Relational operators. + EQ, NE, // [C99 6.5.9] Equality operators. + And, // [C99 6.5.10] Bitwise AND operator. + Xor, // [C99 6.5.11] Bitwise XOR operator. + Or, // [C99 6.5.12] Bitwise OR operator. + LAnd, // [C99 6.5.13] Logical AND operator. + LOr, // [C99 6.5.14] Logical OR operator. + Assign, MulAssign,// [C99 6.5.16] Assignment operators. + DivAssign, RemAssign, + AddAssign, SubAssign, + ShlAssign, ShrAssign, + AndAssign, XorAssign, + OrAssign, + Comma // [C99 6.5.17] Comma operator. + }; +private: + enum { LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + Opcode Opc; + SourceLocation OpLoc; +public: + + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + SourceLocation opLoc) + : Expr(BinaryOperatorClass, ResTy, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + Opc(opc), OpLoc(opLoc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + assert(!isCompoundAssignmentOp() && + "Use ArithAssignBinaryOperator for compound assignments"); + } + + /// \brief Construct an empty binary operator. + explicit BinaryOperator(EmptyShell Empty) + : Expr(BinaryOperatorClass, Empty), Opc(Comma) { } + + SourceLocation getOperatorLoc() const { return OpLoc; } + void setOperatorLoc(SourceLocation L) { OpLoc = L; } + + Opcode getOpcode() const { return Opc; } + void setOpcode(Opcode O) { Opc = O; } + + Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } + void setLHS(Expr *E) { SubExprs[LHS] = E; } + Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } + void setRHS(Expr *E) { SubExprs[RHS] = E; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); + } + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it + /// corresponds to, e.g. "<<=". + static const char *getOpcodeStr(Opcode Op); + + /// \brief Retrieve the binary opcode that corresponds to the given + /// overloaded operator. + static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); + + /// \brief Retrieve the overloaded operator kind that corresponds to + /// the given binary opcode. + static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); + + /// predicates to categorize the respective opcodes. + bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } + bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } + static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } + bool isShiftOp() const { return isShiftOp(Opc); } + + static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; } + bool isBitwiseOp() const { return isBitwiseOp(Opc); } + + static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } + bool isRelationalOp() const { return isRelationalOp(Opc); } + + static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; } + bool isEqualityOp() const { return isEqualityOp(Opc); } + + static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; } + bool isComparisonOp() const { return isComparisonOp(Opc); } + + static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; } + bool isLogicalOp() const { return isLogicalOp(Opc); } + + bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; } + bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;} + bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } + + static bool classof(const Stmt *S) { + return S->getStmtClass() >= firstBinaryOperatorConstant && + S->getStmtClass() <= lastBinaryOperatorConstant; + } + static bool classof(const BinaryOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +protected: + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + SourceLocation opLoc, bool dead) + : Expr(CompoundAssignOperatorClass, ResTy, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + Opc(opc), OpLoc(opLoc) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + BinaryOperator(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty), Opc(MulAssign) { } +}; + +/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep +/// track of the type the operation is performed in. Due to the semantics of +/// these operators, the operands are promoted, the aritmetic performed, an +/// implicit conversion back to the result type done, then the assignment takes +/// place. This captures the intermediate type which the computation is done +/// in. +class CompoundAssignOperator : public BinaryOperator { + QualType ComputationLHSType; + QualType ComputationResultType; +public: + CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, + QualType ResType, QualType CompLHSType, + QualType CompResultType, + SourceLocation OpLoc) + : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true), + ComputationLHSType(CompLHSType), + ComputationResultType(CompResultType) { + assert(isCompoundAssignmentOp() && + "Only should be used for compound assignments"); + } + + /// \brief Build an empty compound assignment operator expression. + explicit CompoundAssignOperator(EmptyShell Empty) + : BinaryOperator(CompoundAssignOperatorClass, Empty) { } + + // The two computation types are the type the LHS is converted + // to for the computation and the type of the result; the two are + // distinct in a few cases (specifically, int+=ptr and ptr-=ptr). + QualType getComputationLHSType() const { return ComputationLHSType; } + void setComputationLHSType(QualType T) { ComputationLHSType = T; } + + QualType getComputationResultType() const { return ComputationResultType; } + void setComputationResultType(QualType T) { ComputationResultType = T; } + + static bool classof(const CompoundAssignOperator *) { return true; } + static bool classof(const Stmt *S) { + return S->getStmtClass() == CompoundAssignOperatorClass; + } +}; + +/// ConditionalOperator - The ?: operator. Note that LHS may be null when the +/// GNU "missing LHS" extension is in use. +/// +class ConditionalOperator : public Expr { + enum { COND, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + SourceLocation QuestionLoc, ColonLoc; +public: + ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, + SourceLocation CLoc, Expr *rhs, QualType t) + : Expr(ConditionalOperatorClass, t, + // FIXME: the type of the conditional operator doesn't + // depend on the type of the conditional, but the standard + // seems to imply that it could. File a bug! + ((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())), + (cond->isValueDependent() || + (lhs && lhs->isValueDependent()) || + (rhs && rhs->isValueDependent()))), + QuestionLoc(QLoc), + ColonLoc(CLoc) { + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + /// \brief Build an empty conditional operator. + explicit ConditionalOperator(EmptyShell Empty) + : Expr(ConditionalOperatorClass, Empty) { } + + // getCond - Return the expression representing the condition for + // the ?: operator. + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + void setCond(Expr *E) { SubExprs[COND] = E; } + + // getTrueExpr - Return the subexpression representing the value of the ?: + // expression if the condition evaluates to true. In most cases this value + // will be the same as getLHS() except a GCC extension allows the left + // subexpression to be omitted, and instead of the condition be returned. + // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x" + // is only evaluated once. + Expr *getTrueExpr() const { + return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]); + } + + // getTrueExpr - Return the subexpression representing the value of 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_or_null<Expr>(SubExprs[LHS]); } + void setLHS(Expr *E) { SubExprs[LHS] = E; } + + Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } + void setRHS(Expr *E) { SubExprs[RHS] = E; } + + SourceLocation getQuestionLoc() const { return QuestionLoc; } + void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } + + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConditionalOperatorClass; + } + static bool classof(const ConditionalOperator *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// AddrLabelExpr - The GNU address of label extension, representing &&label. +class AddrLabelExpr : public Expr { + SourceLocation AmpAmpLoc, LabelLoc; + LabelStmt *Label; +public: + AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, + QualType t) + : Expr(AddrLabelExprClass, t, false, false), + AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} + + /// \brief Build an empty address of a label expression. + explicit AddrLabelExpr(EmptyShell Empty) + : Expr(AddrLabelExprClass, Empty) { } + + SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; } + void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; } + SourceLocation getLabelLoc() const { return LabelLoc; } + void setLabelLoc(SourceLocation L) { LabelLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AmpAmpLoc, LabelLoc); + } + + LabelStmt *getLabel() const { return Label; } + void setLabel(LabelStmt *S) { Label = S; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == AddrLabelExprClass; + } + static bool classof(const AddrLabelExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). +/// The StmtExpr contains a single CompoundStmt node, which it evaluates and +/// takes the value of the last subexpression. +class StmtExpr : public Expr { + Stmt *SubStmt; + SourceLocation LParenLoc, RParenLoc; +public: + // FIXME: Does type-dependence need to be computed differently? + StmtExpr(CompoundStmt *substmt, QualType T, + SourceLocation lp, SourceLocation rp) : + Expr(StmtExprClass, T, T->isDependentType(), false), + SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } + + /// \brief Build an empty statement expression. + explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } + + CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); } + const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } + void setSubStmt(CompoundStmt *S) { SubStmt = S; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LParenLoc, RParenLoc); + } + + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == StmtExprClass; + } + static bool classof(const StmtExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// TypesCompatibleExpr - GNU builtin-in function __builtin_types_compatible_p. +/// This AST node represents a function that returns 1 if two *types* (not +/// expressions) are compatible. The result of this built-in function can be +/// used in integer constant expressions. +class TypesCompatibleExpr : public Expr { + QualType Type1; + QualType Type2; + SourceLocation BuiltinLoc, RParenLoc; +public: + TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, + QualType t1, QualType t2, SourceLocation RP) : + Expr(TypesCompatibleExprClass, ReturnType, false, false), + Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {} + + /// \brief Build an empty __builtin_type_compatible_p expression. + explicit TypesCompatibleExpr(EmptyShell Empty) + : Expr(TypesCompatibleExprClass, Empty) { } + + QualType getArgType1() const { return Type1; } + void setArgType1(QualType T) { Type1 = T; } + QualType getArgType2() const { return Type2; } + void setArgType2(QualType T) { Type2 = T; } + + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == TypesCompatibleExprClass; + } + static bool classof(const TypesCompatibleExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ShuffleVectorExpr - clang-specific builtin-in function +/// __builtin_shufflevector. +/// This AST node represents a operator that does a constant +/// shuffle, similar to LLVM's shufflevector instruction. It takes +/// two vectors and a variable number of constant indices, +/// and returns the appropriately shuffled vector. +class ShuffleVectorExpr : public Expr { + SourceLocation BuiltinLoc, RParenLoc; + + // SubExprs - the list of values passed to the __builtin_shufflevector + // function. The first two are vectors, and the rest are constant + // indices. The number of values in this list is always + // 2+the number of indices in the vector type. + Stmt **SubExprs; + unsigned NumExprs; + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + // FIXME: Can a shufflevector be value-dependent? Does type-dependence need + // to be computed differently? + ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) : + Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) { + + SubExprs = new (C) Stmt*[nexpr]; + for (unsigned i = 0; i < nexpr; i++) + SubExprs[i] = args[i]; + } + + /// \brief Build an empty vector-shuffle expression. + explicit ShuffleVectorExpr(EmptyShell Empty) + : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { } + + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ShuffleVectorExprClass; + } + static bool classof(const ShuffleVectorExpr *) { return true; } + + ~ShuffleVectorExpr() {} + + /// getNumSubExprs - Return the size of the SubExprs array. This includes the + /// constant expression, the actual arguments passed in, and the function + /// pointers. + unsigned getNumSubExprs() const { return NumExprs; } + + /// getExpr - Return the Expr at the specified index. + Expr *getExpr(unsigned Index) { + assert((Index < NumExprs) && "Arg access out of range!"); + return cast<Expr>(SubExprs[Index]); + } + const Expr *getExpr(unsigned Index) const { + assert((Index < NumExprs) && "Arg access out of range!"); + return cast<Expr>(SubExprs[Index]); + } + + void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs); + + unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) { + assert((N < NumExprs - 2) && "Shuffle idx out of range!"); + return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue(); + } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ChooseExpr - GNU builtin-in function __builtin_choose_expr. +/// This AST node is similar to the conditional operator (?:) in C, with +/// the following exceptions: +/// - the test expression must be a integer constant expression. +/// - the expression returned acts like the chosen subexpression in every +/// visible way: the type is the same as that of the chosen subexpression, +/// and all predicates (whether it's an l-value, whether it's an integer +/// constant expression, etc.) return the same result as for the chosen +/// sub-expression. +class ChooseExpr : public Expr { + enum { COND, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. + SourceLocation BuiltinLoc, RParenLoc; +public: + ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t, + SourceLocation RP, bool TypeDependent, bool ValueDependent) + : Expr(ChooseExprClass, t, TypeDependent, ValueDependent), + BuiltinLoc(BLoc), RParenLoc(RP) { + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + /// \brief Build an empty __builtin_choose_expr. + explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } + + /// isConditionTrue - Return whether the condition is true (i.e. not + /// equal to zero). + bool isConditionTrue(ASTContext &C) const; + + /// getChosenSubExpr - Return the subexpression chosen according to the + /// condition. + Expr *getChosenSubExpr(ASTContext &C) const { + return isConditionTrue(C) ? getLHS() : getRHS(); + } + + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + void setCond(Expr *E) { SubExprs[COND] = E; } + Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } + void setLHS(Expr *E) { SubExprs[LHS] = E; } + Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } + void setRHS(Expr *E) { SubExprs[RHS] = E; } + + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ChooseExprClass; + } + static bool classof(const ChooseExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// GNUNullExpr - Implements the GNU __null extension, which is a name +/// for a null pointer constant that has integral type (e.g., int or +/// long) and is the same size and alignment as a pointer. The __null +/// extension is typically only used by system headers, which define +/// NULL as __null in C++ rather than using 0 (which is an integer +/// that may not match the size of a pointer). +class GNUNullExpr : public Expr { + /// TokenLoc - The location of the __null keyword. + SourceLocation TokenLoc; + +public: + GNUNullExpr(QualType Ty, SourceLocation Loc) + : Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { } + + /// \brief Build an empty GNU __null expression. + explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } + + /// getTokenLocation - The location of the __null token. + SourceLocation getTokenLocation() const { return TokenLoc; } + void setTokenLocation(SourceLocation L) { TokenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(TokenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GNUNullExprClass; + } + static bool classof(const GNUNullExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// VAArgExpr, used for the builtin function __builtin_va_arg. +class VAArgExpr : public Expr { + Stmt *Val; + SourceLocation BuiltinLoc, RParenLoc; +public: + VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc) + : Expr(VAArgExprClass, t, t->isDependentType(), false), + Val(e), + BuiltinLoc(BLoc), + RParenLoc(RPLoc) { } + + /// \brief Create an empty __builtin_va_arg expression. + explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } + + const Expr *getSubExpr() const { return cast<Expr>(Val); } + Expr *getSubExpr() { return cast<Expr>(Val); } + void setSubExpr(Expr *E) { Val = E; } + + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == VAArgExprClass; + } + static bool classof(const VAArgExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// @brief Describes an C or C++ initializer list. +/// +/// InitListExpr describes an initializer list, which can be used to +/// initialize objects of different types, including +/// struct/class/union types, arrays, and vectors. For example: +/// +/// @code +/// struct foo x = { 1, { 2, 3 } }; +/// @endcode +/// +/// Prior to semantic analysis, an initializer list will represent the +/// initializer list as written by the user, but will have the +/// placeholder type "void". This initializer list is called the +/// syntactic form of the initializer, and may contain C99 designated +/// initializers (represented as DesignatedInitExprs), initializations +/// of subobject members without explicit braces, and so on. Clients +/// interested in the original syntax of the initializer list should +/// use the syntactic form of the initializer list. +/// +/// After semantic analysis, the initializer list will represent the +/// semantic form of the initializer, where the initializations of all +/// subobjects are made explicit with nested InitListExpr nodes and +/// C99 designators have been eliminated by placing the designated +/// initializations into the subobject they initialize. Additionally, +/// any "holes" in the initialization, where no initializer has been +/// specified for a particular subobject, will be replaced with +/// implicitly-generated ImplicitValueInitExpr expressions that +/// value-initialize the subobjects. Note, however, that the +/// initializer lists may still have fewer initializers than there are +/// elements to initialize within the object. +/// +/// Given the semantic form of the initializer list, one can retrieve +/// the original syntactic form of that initializer list (if it +/// exists) using getSyntacticForm(). Since many initializer lists +/// have the same syntactic and semantic forms, getSyntacticForm() may +/// return NULL, indicating that the current initializer list also +/// serves as its syntactic form. +class InitListExpr : public Expr { + // FIXME: Eliminate this vector in favor of ASTContext allocation + typedef ASTVector<Stmt *> InitExprsTy; + InitExprsTy InitExprs; + SourceLocation LBraceLoc, RBraceLoc; + + /// Contains the initializer list that describes the syntactic form + /// written in the source code. + InitListExpr *SyntacticForm; + + /// If this initializer list initializes a union, specifies which + /// field within the union will be initialized. + FieldDecl *UnionFieldInit; + + /// 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, + SourceLocation rbraceloc); + + /// \brief Build an empty initializer list. + explicit InitListExpr(ASTContext &C, EmptyShell Empty) + : Expr(InitListExprClass, Empty), InitExprs(C) { } + + unsigned getNumInits() const { return InitExprs.size(); } + + const Expr* getInit(unsigned Init) const { + assert(Init < getNumInits() && "Initializer access out of range!"); + return cast_or_null<Expr>(InitExprs[Init]); + } + + Expr* getInit(unsigned Init) { + assert(Init < getNumInits() && "Initializer access out of range!"); + return cast_or_null<Expr>(InitExprs[Init]); + } + + void setInit(unsigned Init, Expr *expr) { + assert(Init < getNumInits() && "Initializer access out of range!"); + InitExprs[Init] = expr; + } + + /// \brief Reserve space for some number of initializers. + void reserveInits(ASTContext &C, unsigned NumInits); + + /// @brief Specify the number of initializers + /// + /// If there are more than @p NumInits initializers, the remaining + /// initializers will be destroyed. If there are fewer than @p + /// NumInits initializers, NULL expressions will be added for the + /// unknown initializers. + void resizeInits(ASTContext &Context, unsigned NumInits); + + /// @brief Updates the initializer at index @p Init with the new + /// expression @p expr, and returns the old expression at that + /// location. + /// + /// When @p Init is out of range for this initializer list, the + /// initializer list will be extended with NULL expressions to + /// accomodate the new entry. + Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); + + /// \brief If this initializes a union, specifies which field in the + /// union to initialize. + /// + /// Typically, this field is the first named field within the + /// union. However, a designated initializer can specify the + /// initialization of a different field within the union. + FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; } + void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; } + + // Explicit InitListExpr's originate from source code (and have valid source + // locations). Implicit InitListExpr's are created by the semantic analyzer. + bool isExplicit() { + return LBraceLoc.isValid() && RBraceLoc.isValid(); + } + + SourceLocation getLBraceLoc() const { return LBraceLoc; } + void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; } + + /// @brief Retrieve the initializer list that describes the + /// syntactic form of the initializer. + /// + /// + InitListExpr *getSyntacticForm() const { return SyntacticForm; } + void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; } + + bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; } + void sawArrayRangeDesignator(bool ARD = true) { + HadArrayRangeDesignator = ARD; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(LBraceLoc, RBraceLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == InitListExprClass; + } + static bool classof(const InitListExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + typedef InitExprsTy::iterator iterator; + typedef InitExprsTy::reverse_iterator reverse_iterator; + + iterator begin() { return InitExprs.begin(); } + iterator end() { return InitExprs.end(); } + reverse_iterator rbegin() { return InitExprs.rbegin(); } + reverse_iterator rend() { return InitExprs.rend(); } +}; + +/// @brief Represents a C99 designated initializer expression. +/// +/// A designated initializer expression (C99 6.7.8) contains one or +/// more designators (which can be field designators, array +/// designators, or GNU array-range designators) followed by an +/// expression that initializes the field or element(s) that the +/// designators refer to. For example, given: +/// +/// @code +/// struct point { +/// double x; +/// double y; +/// }; +/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; +/// @endcode +/// +/// The InitListExpr contains three DesignatedInitExprs, the first of +/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two +/// designators, one array designator for @c [2] followed by one field +/// designator for @c .y. The initalization expression will be 1.0. +class DesignatedInitExpr : public Expr { +public: + /// \brief Forward declaration of the Designator class. + class Designator; + +private: + /// The location of the '=' or ':' prior to the actual initializer + /// expression. + SourceLocation EqualOrColonLoc; + + /// Whether this designated initializer used the GNU deprecated + /// syntax rather than the C99 '=' syntax. + bool GNUSyntax : 1; + + /// 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; + + + DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators, + const Designator *Designators, + SourceLocation EqualOrColonLoc, bool GNUSyntax, + Expr **IndexExprs, unsigned NumIndexExprs, + Expr *Init); + + explicit DesignatedInitExpr(unsigned NumSubExprs) + : Expr(DesignatedInitExprClass, EmptyShell()), + NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } + +protected: + virtual void DoDestroy(ASTContext &C); + + void DestroyDesignators(ASTContext &C); + +public: + /// A field designator, e.g., ".x". + struct FieldDesignator { + /// Refers to the field that is being initialized. The low bit + /// of this field determines whether this is actually a pointer + /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When + /// initially constructed, a field designator will store an + /// IdentifierInfo*. After semantic analysis has resolved that + /// name, the field designator will instead store a FieldDecl*. + uintptr_t NameOrField; + + /// The location of the '.' in the designated initializer. + unsigned DotLoc; + + /// The location of the field name in the designated initializer. + unsigned FieldLoc; + }; + + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator { + /// Location of the first index expression within the designated + /// initializer expression's list of subexpressions. + unsigned Index; + /// The location of the '[' starting the array range designator. + unsigned LBracketLoc; + /// The location of the ellipsis separating the start and end + /// indices. Only valid for GNU array-range designators. + unsigned EllipsisLoc; + /// The location of the ']' terminating the array range designator. + unsigned RBracketLoc; + }; + + /// @brief Represents a single C99 designator. + /// + /// @todo This class is infuriatingly similar to clang::Designator, + /// but minor differences (storing indices vs. storing pointers) + /// keep us from reusing it. Try harder, later, to rectify these + /// differences. + class Designator { + /// @brief The kind of designator this describes. + enum { + FieldDesignator, + ArrayDesignator, + ArrayRangeDesignator + } Kind; + + union { + /// A field designator, e.g., ".x". + struct FieldDesignator Field; + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator ArrayOrRange; + }; + friend class DesignatedInitExpr; + + public: + Designator() {} + + /// @brief Initializes a field designator. + Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, + SourceLocation FieldLoc) + : Kind(FieldDesignator) { + Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; + Field.DotLoc = DotLoc.getRawEncoding(); + Field.FieldLoc = FieldLoc.getRawEncoding(); + } + + /// @brief Initializes an array designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation RBracketLoc) + : Kind(ArrayDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + /// @brief Initializes a GNU array-range designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, SourceLocation RBracketLoc) + : Kind(ArrayRangeDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + bool isFieldDesignator() const { return Kind == FieldDesignator; } + bool isArrayDesignator() const { return Kind == ArrayDesignator; } + bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } + + IdentifierInfo * getFieldName(); + + FieldDecl *getField() { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + if (Field.NameOrField & 0x01) + return 0; + else + return reinterpret_cast<FieldDecl *>(Field.NameOrField); + } + + void setField(FieldDecl *FD) { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + Field.NameOrField = reinterpret_cast<uintptr_t>(FD); + } + + SourceLocation getDotLoc() const { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + return SourceLocation::getFromRawEncoding(Field.DotLoc); + } + + SourceLocation getFieldLoc() const { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + return SourceLocation::getFromRawEncoding(Field.FieldLoc); + } + + SourceLocation getLBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(Kind == ArrayRangeDesignator && + "Only valid on an array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc); + } + + unsigned getFirstExprIndex() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return ArrayOrRange.Index; + } + + SourceLocation getStartLocation() const { + if (Kind == FieldDesignator) + return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); + else + return getLBracketLoc(); + } + }; + + static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, + unsigned NumDesignators, + Expr **IndexExprs, unsigned NumIndexExprs, + SourceLocation EqualOrColonLoc, + bool GNUSyntax, Expr *Init); + + static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs); + + /// @brief Returns the number of designators in this initializer. + unsigned size() const { return NumDesignators; } + + // Iterator access to the designators. + typedef Designator* designators_iterator; + designators_iterator designators_begin() { return Designators; } + designators_iterator designators_end() { + return Designators + NumDesignators; + } + + Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } + + void setDesignators(ASTContext &C, const Designator *Desigs, + unsigned NumDesigs); + + Expr *getArrayIndex(const Designator& D); + Expr *getArrayRangeStart(const Designator& D); + Expr *getArrayRangeEnd(const Designator& D); + + /// @brief Retrieve the location of the '=' that precedes the + /// initializer value itself, if present. + SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } + void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } + + /// @brief Determines whether this designated initializer used the + /// deprecated GNU syntax for designated initializers. + bool usesGNUSyntax() const { return GNUSyntax; } + void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } + + /// @brief Retrieve the initializer value. + Expr *getInit() const { + return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); + } + + void setInit(Expr *init) { + *child_begin() = init; + } + + /// \brief Retrieve the total number of subexpressions in this + /// designated initializer expression, including the actual + /// initialized value and any expressions that occur within array + /// and array-range designators. + unsigned getNumSubExprs() const { return NumSubExprs; } + + Expr *getSubExpr(unsigned Idx) { + assert(Idx < NumSubExprs && "Subscript out of range"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx]; + } + + void setSubExpr(unsigned Idx, Expr *E) { + assert(Idx < NumSubExprs && "Subscript out of range"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E; + } + + /// \brief Replaces the designator at index @p Idx with the series + /// of designators in [First, Last). + void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, + const Designator *Last); + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DesignatedInitExprClass; + } + static bool classof(const DesignatedInitExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Represents an implicitly-generated value initialization of +/// an object of a given type. +/// +/// Implicit value initializations occur within semantic initializer +/// list expressions (InitListExpr) as placeholders for subobject +/// initializations not explicitly specified by the user. +/// +/// \see InitListExpr +class ImplicitValueInitExpr : public Expr { +public: + explicit ImplicitValueInitExpr(QualType ty) + : Expr(ImplicitValueInitExprClass, ty, false, false) { } + + /// \brief Construct an empty implicit value initialization. + explicit ImplicitValueInitExpr(EmptyShell Empty) + : Expr(ImplicitValueInitExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ImplicitValueInitExprClass; + } + static bool classof(const ImplicitValueInitExpr *) { return true; } + + virtual SourceRange getSourceRange() const { + return SourceRange(); + } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +class ParenListExpr : public Expr { + Stmt **Exprs; + unsigned NumExprs; + SourceLocation LParenLoc, RParenLoc; + +protected: + virtual void DoDestroy(ASTContext& C); + +public: + ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, + unsigned numexprs, SourceLocation rparenloc); + + ~ParenListExpr() {} + + /// \brief Build an empty paren list. + //explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + + unsigned getNumExprs() const { return NumExprs; } + + const Expr* getExpr(unsigned Init) const { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null<Expr>(Exprs[Init]); + } + + Expr* getExpr(unsigned Init) { + assert(Init < getNumExprs() && "Initializer access out of range!"); + return cast_or_null<Expr>(Exprs[Init]); + } + + Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(LParenLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenListExprClass; + } + static bool classof(const ParenListExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +//===----------------------------------------------------------------------===// +// Clang Extensions +//===----------------------------------------------------------------------===// + + +/// ExtVectorElementExpr - This represents access to specific elements of a +/// vector, and may occur on the left hand side or right hand side. For example +/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. +/// +/// Note that the base may have either vector or pointer to vector type, just +/// like a struct field reference. +/// +class ExtVectorElementExpr : public Expr { + Stmt *Base; + IdentifierInfo *Accessor; + SourceLocation AccessorLoc; +public: + ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor, + SourceLocation loc) + : Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(), + base->isValueDependent()), + Base(base), Accessor(&accessor), AccessorLoc(loc) {} + + /// \brief Build an empty vector element expression. + explicit ExtVectorElementExpr(EmptyShell Empty) + : Expr(ExtVectorElementExprClass, Empty) { } + + const Expr *getBase() const { return cast<Expr>(Base); } + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr *E) { Base = E; } + + IdentifierInfo &getAccessor() const { return *Accessor; } + void setAccessor(IdentifierInfo *II) { Accessor = II; } + + SourceLocation getAccessorLoc() const { return AccessorLoc; } + void setAccessorLoc(SourceLocation L) { AccessorLoc = L; } + + /// getNumElements - Get the number of components being selected. + unsigned getNumElements() const; + + /// containsDuplicateElements - Return true if any element access is + /// repeated. + bool containsDuplicateElements() const; + + /// getEncodedElementAccess - Encode the elements accessed into an llvm + /// aggregate Constant of ConstantInt(s). + void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const; + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), AccessorLoc); + } + + /// isArrow - Return true if the base expression is a pointer to vector, + /// return false if the base expression is a vector. + bool isArrow() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExtVectorElementExprClass; + } + static bool classof(const ExtVectorElementExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. +/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } +class BlockExpr : public Expr { +protected: + BlockDecl *TheBlock; + bool HasBlockDeclRefExprs; +public: + BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) + : Expr(BlockExprClass, ty, ty->isDependentType(), false), + TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} + + /// \brief Build an empty block expression. + explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } + + const BlockDecl *getBlockDecl() const { return TheBlock; } + BlockDecl *getBlockDecl() { return TheBlock; } + void setBlockDecl(BlockDecl *BD) { TheBlock = BD; } + + // Convenience functions for probing the underlying BlockDecl. + SourceLocation getCaretLocation() const; + const Stmt *getBody() const; + Stmt *getBody(); + + virtual SourceRange getSourceRange() const { + return SourceRange(getCaretLocation(), getBody()->getLocEnd()); + } + + /// getFunctionType - Return the underlying function type for this block. + const FunctionType *getFunctionType() const; + + /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr + /// inside of the block that reference values outside the block. + bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; } + void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == BlockExprClass; + } + static bool classof(const BlockExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// BlockDeclRefExpr - A reference to a declared variable, function, +/// enum, etc. +class BlockDeclRefExpr : public Expr { + ValueDecl *D; + SourceLocation Loc; + bool IsByRef : 1; + bool ConstQualAdded : 1; +public: + // FIXME: Fix type/value dependence! + BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, + bool constAdded = false) + : Expr(BlockDeclRefExprClass, t, false, false), D(d), Loc(l), IsByRef(ByRef), + ConstQualAdded(constAdded) {} + + // \brief Build an empty reference to a declared variable in a + // block. + explicit BlockDeclRefExpr(EmptyShell Empty) + : Expr(BlockDeclRefExprClass, Empty) { } + + ValueDecl *getDecl() { return D; } + const ValueDecl *getDecl() const { return D; } + void setDecl(ValueDecl *VD) { D = VD; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + virtual 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 + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h new file mode 100644 index 0000000..0c493f3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h @@ -0,0 +1,2262 @@ +//===--- ExprCXX.h - Classes for representing expressions -------*- 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 Expr interface and subclasses for C++ expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPRCXX_H +#define LLVM_CLANG_AST_EXPRCXX_H + +#include "clang/Basic/TypeTraits.h" +#include "clang/AST/Expr.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/AST/TemplateBase.h" + +namespace clang { + + class CXXConstructorDecl; + class CXXDestructorDecl; + class CXXMethodDecl; + class CXXTemporary; + class TemplateArgumentListInfo; + +//===--------------------------------------------------------------------===// +// C++ Expressions. +//===--------------------------------------------------------------------===// + +/// \brief A call to an overloaded operator written using operator +/// syntax. +/// +/// Represents a call to an overloaded operator written using operator +/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a +/// normal call, this AST node provides better information about the +/// syntactic representation of the call. +/// +/// In a C++ template, this expression node kind will be used whenever +/// any of the arguments are type-dependent. In this case, the +/// function itself will be a (possibly empty) set of functions and +/// function templates that were found by name lookup at template +/// definition time. +class CXXOperatorCallExpr : public CallExpr { + /// \brief The overloaded operator. + OverloadedOperatorKind Operator; + +public: + CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, + Expr **args, unsigned numargs, QualType t, + SourceLocation operatorloc) + : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc), + Operator(Op) {} + explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : + CallExpr(C, CXXOperatorCallExprClass, Empty) { } + + + /// getOperator - Returns the kind of overloaded operator that this + /// expression refers to. + OverloadedOperatorKind getOperator() const { return Operator; } + void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; } + + /// getOperatorLoc - Returns the location of the operator symbol in + /// the expression. When @c getOperator()==OO_Call, this is the + /// location of the right parentheses; when @c + /// getOperator()==OO_Subscript, this is the location of the right + /// bracket. + SourceLocation getOperatorLoc() const { return getRParenLoc(); } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXOperatorCallExprClass; + } + static bool classof(const CXXOperatorCallExpr *) { return true; } +}; + +/// CXXMemberCallExpr - Represents a call to a member function that +/// may be written either with member call syntax (e.g., "obj.func()" +/// or "objptr->func()") or with normal function-call syntax +/// ("func()") within a member function that ends up calling a member +/// function. The callee in either case is a MemberExpr that contains +/// both the object argument and the member function, while the +/// arguments are the arguments within the parentheses (not including +/// the object argument). +class CXXMemberCallExpr : public CallExpr { +public: + CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs, + QualType t, SourceLocation rparenloc) + : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {} + + CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) + : CallExpr(C, CXXMemberCallExprClass, Empty) { } + + /// getImplicitObjectArgument - Retrieves the implicit object + /// argument for the member call. For example, in "x.f(5)", this + /// operation would return "x". + Expr *getImplicitObjectArgument(); + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXMemberCallExprClass; + } + static bool classof(const CXXMemberCallExpr *) { return true; } +}; + +/// CXXNamedCastExpr - Abstract class common to all of the C++ "named" +/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c +/// const_cast. +/// +/// This abstract class is inherited by all of the classes +/// representing "named" casts, e.g., CXXStaticCastExpr, +/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr. +class CXXNamedCastExpr : public ExplicitCastExpr { +private: + SourceLocation Loc; // the location of the casting op + +protected: + CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} + + explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) + : ExplicitCastExpr(SC, Shell) { } + +public: + const char *getCastName() const; + + /// \brief Retrieve the location of the cast operator keyword, e.g., + /// "static_cast". + SourceLocation getOperatorLoc() const { return Loc; } + void setOperatorLoc(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd()); + } + static bool classof(const Stmt *T) { + switch (T->getStmtClass()) { + case CXXStaticCastExprClass: + case CXXDynamicCastExprClass: + case CXXReinterpretCastExprClass: + case CXXConstCastExprClass: + return true; + default: + return false; + } + } + static bool classof(const CXXNamedCastExpr *) { return true; } +}; + +/// 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). +class CXXStaticCastExpr : public CXXNamedCastExpr { +public: + CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} + + explicit CXXStaticCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXStaticCastExprClass; + } + static bool classof(const CXXStaticCastExpr *) { return true; } +}; + +/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression +/// (C++ [expr.dynamic.cast]), which may perform a run-time check to +/// determine how to perform the type cast. +/// +/// This expression node represents a dynamic cast, e.g., +/// @c dynamic_cast<Derived*>(BasePtr). +class CXXDynamicCastExpr : public CXXNamedCastExpr { +public: + CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, + writtenTy, l) {} + + explicit CXXDynamicCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDynamicCastExprClass; + } + static bool classof(const CXXDynamicCastExpr *) { return true; } +}; + +/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++ +/// [expr.reinterpret.cast]), which provides a differently-typed view +/// of a value but performs no actual work at run time. +/// +/// This expression node represents a reinterpret cast, e.g., +/// @c reinterpret_cast<int>(VoidPtr). +class CXXReinterpretCastExpr : public CXXNamedCastExpr { +public: + CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, + TypeSourceInfo *writtenTy, SourceLocation l) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, + writtenTy, l) {} + + explicit CXXReinterpretCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXReinterpretCastExprClass; + } + static bool classof(const CXXReinterpretCastExpr *) { return true; } +}; + +/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]), +/// which can remove type qualifiers but does not change the underlying value. +/// +/// This expression node represents a const cast, e.g., +/// @c const_cast<char*>(PtrToConstChar). +class CXXConstCastExpr : public CXXNamedCastExpr { +public: + CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, + CXXBaseSpecifierArray(), writtenTy, l) {} + + explicit CXXConstCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXConstCastExprClass; + } + static bool classof(const CXXConstCastExpr *) { return true; } +}; + +/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal. +/// +class CXXBoolLiteralExpr : public Expr { + bool Value; + SourceLocation Loc; +public: + CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : + Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {} + + explicit CXXBoolLiteralExpr(EmptyShell Empty) + : Expr(CXXBoolLiteralExprClass, Empty) { } + + bool getValue() const { return Value; } + void setValue(bool V) { Value = V; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBoolLiteralExprClass; + } + static bool classof(const CXXBoolLiteralExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal +class CXXNullPtrLiteralExpr : public Expr { + SourceLocation Loc; +public: + CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : + Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {} + + explicit CXXNullPtrLiteralExpr(EmptyShell Empty) + : Expr(CXXNullPtrLiteralExprClass, Empty) { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNullPtrLiteralExprClass; + } + static bool classof(const CXXNullPtrLiteralExpr *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets +/// the type_info that corresponds to the supplied type, or the (possibly +/// dynamic) type of the supplied expression. +/// +/// This represents code like @c typeid(int) or @c typeid(*objPtr) +class CXXTypeidExpr : public Expr { +private: + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; + SourceRange Range; + +public: + CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are dependent + Operand->getType()->isDependentType()), + Operand(Operand), Range(R) { } + + CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are dependent + Operand->isTypeDependent() || Operand->isValueDependent()), + Operand(Operand), Range(R) { } + + CXXTypeidExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXTypeidExprClass, Empty) { + if (isExpr) + Operand = (Expr*)0; + 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; + + /// \brief Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + return Operand.get<TypeSourceInfo *>(); + } + + void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { + 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; + } + + virtual SourceRange getSourceRange() const { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTypeidExprClass; + } + static bool classof(const CXXTypeidExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXThisExpr - Represents the "this" expression in C++, which is a +/// pointer to the object on which the current member function is +/// executing (C++ [expr.prim]p3). Example: +/// +/// @code +/// class Foo { +/// public: +/// void bar(); +/// void test() { this->bar(); } +/// }; +/// @endcode +class CXXThisExpr : public Expr { + SourceLocation Loc; + bool Implicit : 1; + +public: + CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) + : Expr(CXXThisExprClass, Type, + // 'this' is type-dependent if the class type of the enclosing + // member function is dependent (C++ [temp.dep.expr]p2) + Type->isDependentType(), Type->isDependentType()), + Loc(L), Implicit(isImplicit) { } + + CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + bool isImplicit() const { return Implicit; } + void setImplicit(bool I) { Implicit = I; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThisExprClass; + } + static bool classof(const CXXThisExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles +/// 'throw' and 'throw' assignment-expression. When +/// assignment-expression isn't present, Op will be null. +/// +class CXXThrowExpr : public Expr { + Stmt *Op; + SourceLocation ThrowLoc; +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 + // can by null, if the optional expression to throw isn't present. + CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) : + Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {} + CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} + + const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } + Expr *getSubExpr() { return cast_or_null<Expr>(Op); } + void setSubExpr(Expr *E) { Op = E; } + + SourceLocation getThrowLoc() const { return ThrowLoc; } + void setThrowLoc(SourceLocation L) { ThrowLoc = L; } + + virtual SourceRange getSourceRange() const { + if (getSubExpr() == 0) + return SourceRange(ThrowLoc, ThrowLoc); + return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThrowExprClass; + } + static bool classof(const CXXThrowExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a +/// function call argument that was created from the corresponding +/// parameter's default argument, when the call did not explicitly +/// supply arguments for all of the parameters. +class CXXDefaultArgExpr : public Expr { + /// \brief The parameter whose default is being used. + /// + /// 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; + +protected: + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) + : Expr(SC, + param->hasUnparsedDefaultArg() + ? param->getType().getNonReferenceType() + : param->getDefaultArg()->getType(), + false, false), + Param(param, false), Loc(Loc) { } + + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, + Expr *SubExpr) + : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) { + *reinterpret_cast<Expr **>(this + 1) = SubExpr; + } + +protected: + virtual void DoDestroy(ASTContext &C); + +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, + ParmVarDecl *Param) { + return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); + } + + // 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, + SourceLocation Loc, + 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(); } + + /// isExprStored - Return true if this expression owns the expression. + bool isExprStored() const { return Param.getInt(); } + + // Retrieve the actual argument to the function call. + const Expr *getExpr() const { + if (Param.getInt()) + return *reinterpret_cast<Expr const * const*> (this + 1); + return getParam()->getDefaultArg(); + } + Expr *getExpr() { + if (Param.getInt()) + return *reinterpret_cast<Expr **> (this + 1); + return getParam()->getDefaultArg(); + } + + void setExpr(Expr *E) { + Param.setInt(true); + Param.setPointer((ParmVarDecl*)E); + } + + /// \brief Retrieve the location where this default argument was actually + /// used. + SourceLocation getUsedLocation() const { return Loc; } + void setUsedLocation(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { + // Default argument expressions have no representation in the + // source, so they have an empty source range. + return SourceRange(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDefaultArgExprClass; + } + static bool classof(const CXXDefaultArgExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTemporary - Represents a C++ temporary. +class CXXTemporary { + /// Destructor - The destructor that needs to be called. + const CXXDestructorDecl *Destructor; + + CXXTemporary(const CXXDestructorDecl *destructor) + : Destructor(destructor) { } + ~CXXTemporary() { } + +public: + static CXXTemporary *Create(ASTContext &C, + const CXXDestructorDecl *Destructor); + + void Destroy(ASTContext &Ctx); + + const CXXDestructorDecl *getDestructor() const { return Destructor; } +}; + +/// \brief Represents binding an expression to a temporary. +/// +/// This ensures the destructor is called for the temporary. It should only be +/// needed for non-POD, non-trivially destructable class types. For example: +/// +/// \code +/// struct S { +/// S() { } // User defined constructor makes S non-POD. +/// ~S() { } // User defined destructor makes it non-trivial. +/// }; +/// void test() { +/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. +/// } +/// \endcode +class CXXBindTemporaryExpr : public Expr { + CXXTemporary *Temp; + + Stmt *SubExpr; + + CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) + : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), + Temp(temp), SubExpr(subexpr) { } + ~CXXBindTemporaryExpr() { } + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + CXXBindTemporaryExpr(EmptyShell Empty) + : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, + Expr* SubExpr); + + CXXTemporary *getTemporary() { return Temp; } + const CXXTemporary *getTemporary() const { return Temp; } + void setTemporary(CXXTemporary *T) { Temp = T; } + + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBindTemporaryExprClass; + } + static bool classof(const CXXBindTemporaryExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXBindReferenceExpr - Represents binding an expression to a reference. +/// In the example: +/// +/// const int &i = 10; +/// +/// a bind reference expression is inserted to indicate that 10 is bound to +/// a reference, and that a temporary needs to be created to hold the +/// value. +class CXXBindReferenceExpr : public Expr { + // SubExpr - The expression being bound. + Stmt *SubExpr; + + // ExtendsLifetime - Whether binding this reference extends the lifetime of + // the expression being bound. FIXME: Add C++ reference. + bool ExtendsLifetime; + + /// RequiresTemporaryCopy - Whether binding the subexpression requires a + /// temporary copy. + bool RequiresTemporaryCopy; + + CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime, + bool RequiresTemporaryCopy) + : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false), + SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime), + RequiresTemporaryCopy(RequiresTemporaryCopy) { } + ~CXXBindReferenceExpr() { } + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr, + bool ExtendsLifetime, + bool RequiresTemporaryCopy); + + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } + + /// requiresTemporaryCopy - Whether binding the subexpression requires a + /// temporary copy. + bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; } + + // extendsLifetime - Whether binding this reference extends the lifetime of + // the expression being bound. FIXME: Add C++ reference. + bool extendsLifetime() { return ExtendsLifetime; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBindReferenceExprClass; + } + static bool classof(const CXXBindReferenceExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXConstructExpr - Represents a call to a C++ constructor. +class CXXConstructExpr : public Expr { +public: + enum ConstructionKind { + CK_Complete, + CK_NonVirtualBase, + CK_VirtualBase + }; + +private: + CXXConstructorDecl *Constructor; + + SourceLocation Loc; + bool Elidable : 1; + bool ZeroInitialization : 1; + unsigned ConstructKind : 2; + Stmt **Args; + unsigned NumArgs; + +protected: + CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + SourceLocation Loc, + CXXConstructorDecl *d, bool elidable, + Expr **args, unsigned numargs, + bool ZeroInitialization = false, + ConstructionKind ConstructKind = CK_Complete); + ~CXXConstructExpr() { } + + virtual void DoDestroy(ASTContext &C); + +public: + /// \brief Construct an empty C++ construction expression that will store + /// \p numargs arguments. + CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs); + + static CXXConstructExpr *Create(ASTContext &C, QualType T, + SourceLocation Loc, + CXXConstructorDecl *D, bool Elidable, + Expr **Args, unsigned NumArgs, + bool ZeroInitialization = false, + ConstructionKind ConstructKind = CK_Complete); + + + 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; } + + /// \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) { + ConstructKind = CK; + } + + typedef ExprIterator arg_iterator; + typedef ConstExprIterator const_arg_iterator; + + arg_iterator arg_begin() { return Args; } + arg_iterator arg_end() { return Args + NumArgs; } + const_arg_iterator arg_begin() const { return Args; } + const_arg_iterator arg_end() const { return Args + NumArgs; } + + Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); } + unsigned getNumArgs() const { return NumArgs; } + + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(Args[Arg]); + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(Args[Arg]); + } + + /// setArg - Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < NumArgs && "Arg access out of range!"); + Args[Arg] = ArgExpr; + } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXConstructExprClass || + T->getStmtClass() == CXXTemporaryObjectExprClass; + } + static bool classof(const CXXConstructExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion +/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c +/// x = int(0.5); +class CXXFunctionalCastExpr : public ExplicitCastExpr { + SourceLocation TyBeginLoc; + SourceLocation RParenLoc; +public: + CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, + SourceLocation tyBeginLoc, CastKind kind, + Expr *castExpr, CXXBaseSpecifierArray BasePath, + SourceLocation rParenLoc) + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, + BasePath, writtenTy), + TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + + explicit CXXFunctionalCastExpr(EmptyShell Shell) + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { } + + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } + void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFunctionalCastExprClass; + } + static bool classof(const CXXFunctionalCastExpr *) { return true; } +}; + +/// @brief Represents a C++ functional cast expression that builds a +/// temporary object. +/// +/// 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. If N == 0 but no +/// constructor will be called (because the functional cast is +/// performing a value-initialized an object whose class type has no +/// user-declared constructors), CXXZeroInitValueExpr will represent +/// the functional cast. Finally, with N == 1 arguments the functional +/// cast expression will be represented by CXXFunctionalCastExpr. +/// Example: +/// @code +/// struct X { X(int, float); } +/// +/// X create_X() { +/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr +/// }; +/// @endcode +class CXXTemporaryObjectExpr : public CXXConstructExpr { + SourceLocation TyBeginLoc; + SourceLocation RParenLoc; + +public: + CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, + QualType writtenTy, SourceLocation tyBeginLoc, + Expr **Args,unsigned NumArgs, + SourceLocation rParenLoc, + bool ZeroInitialization = false); + + ~CXXTemporaryObjectExpr() { } + + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTemporaryObjectExprClass; + } + static bool classof(const CXXTemporaryObjectExpr *) { return true; } +}; + +/// CXXZeroInitValueExpr - [C++ 5.2.3p2] +/// Expression "T()" which creates a value-initialized rvalue of type +/// T, which is either a non-class type or a class type without any +/// user-defined constructors. +/// +class CXXZeroInitValueExpr : public Expr { + SourceLocation TyBeginLoc; + SourceLocation RParenLoc; + +public: + CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc, + SourceLocation rParenLoc ) : + Expr(CXXZeroInitValueExprClass, ty, false, false), + TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + explicit CXXZeroInitValueExpr(EmptyShell Shell) + : Expr(CXXZeroInitValueExprClass, Shell) { } + + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + /// @brief Whether this initialization expression was + /// implicitly-generated. + bool isImplicit() const { + return TyBeginLoc.isInvalid() && RParenLoc.isInvalid(); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXZeroInitValueExprClass; + } + static bool classof(const CXXZeroInitValueExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// 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; + // Was the form (type-id) used? Otherwise, it was new-type-id. + bool ParenTypeId : 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; + // The number of placement new arguments. + unsigned NumPlacementArgs : 14; + // 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. + 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; + + SourceLocation StartLoc; + SourceLocation EndLoc; + +public: + CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, + Expr **placementArgs, unsigned numPlaceArgs, bool ParenTypeId, + Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, + Expr **constructorArgs, unsigned numConsArgs, + FunctionDecl *operatorDelete, QualType ty, + SourceLocation startLoc, SourceLocation endLoc); + explicit CXXNewExpr(EmptyShell Shell) + : Expr(CXXNewExprClass, Shell), SubExprs(0) { } + + void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, + unsigned numConsArgs); + + virtual void DoDestroy(ASTContext &C); + + QualType getAllocatedType() const { + assert(getType()->isPointerType()); + return getType()->getAs<PointerType>()->getPointeeType(); + } + + 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() { + return Array ? cast<Expr>(SubExprs[0]) : 0; + } + const Expr *getArraySize() const { + return Array ? cast<Expr>(SubExprs[0]) : 0; + } + + unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + Expr *getPlacementArg(unsigned i) { + assert(i < NumPlacementArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + i]); + } + const Expr *getPlacementArg(unsigned i) const { + assert(i < NumPlacementArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + i]); + } + + bool isGlobalNew() const { return GlobalNew; } + void setGlobalNew(bool V) { GlobalNew = V; } + bool isParenTypeId() const { return ParenTypeId; } + void setParenTypeId(bool V) { ParenTypeId = V; } + bool hasInitializer() const { return Initializer; } + void setHasInitializer(bool V) { Initializer = V; } + + unsigned getNumConstructorArgs() const { return NumConstructorArgs; } + Expr *getConstructorArg(unsigned i) { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + } + const Expr *getConstructorArg(unsigned i) const { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + } + + typedef ExprIterator arg_iterator; + typedef ConstExprIterator const_arg_iterator; + + arg_iterator placement_arg_begin() { + return SubExprs + Array; + } + arg_iterator placement_arg_end() { + return SubExprs + Array + getNumPlacementArgs(); + } + const_arg_iterator placement_arg_begin() const { + return SubExprs + Array; + } + const_arg_iterator placement_arg_end() const { + return SubExprs + Array + 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(); + } + const_arg_iterator raw_arg_begin() const { return SubExprs; } + const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } + + + SourceLocation getStartLoc() const { return StartLoc; } + void setStartLoc(SourceLocation L) { StartLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(StartLoc, EndLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNewExprClass; + } + static bool classof(const CXXNewExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXDeleteExpr - A delete expression for memory deallocation and destructor +/// calls, e.g. "delete[] pArray". +class CXXDeleteExpr : public Expr { + // Is this a forced global delete, i.e. "::delete"? + bool GlobalDelete : 1; + // Is this the array form of delete, i.e. "delete[]"? + bool ArrayForm : 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, + FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) + : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete), + ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg), + Loc(loc) { } + + bool isGlobalDelete() const { return GlobalDelete; } + bool isArrayForm() const { return ArrayForm; } + + FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + + Expr *getArgument() { return cast<Expr>(Argument); } + const Expr *getArgument() const { return cast<Expr>(Argument); } + + virtual SourceRange getSourceRange() const { + return SourceRange(Loc, Argument->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDeleteExprClass; + } + static bool classof(const CXXDeleteExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Structure used to store the type being destroyed by a +/// pseudo-destructor expression. +class PseudoDestructorTypeStorage { + /// \brief Either the type source information or the name of the type, if + /// it couldn't be resolved due to type-dependence. + llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; + + /// \brief The starting source location of the pseudo-destructor type. + SourceLocation Location; + +public: + PseudoDestructorTypeStorage() { } + + PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) + : Type(II), Location(Loc) { } + + PseudoDestructorTypeStorage(TypeSourceInfo *Info); + + TypeSourceInfo *getTypeSourceInfo() const { + return Type.dyn_cast<TypeSourceInfo *>(); + } + + IdentifierInfo *getIdentifier() const { + return Type.dyn_cast<IdentifierInfo *>(); + } + + SourceLocation getLocation() const { return Location; } +}; + +/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). +/// +/// A pseudo-destructor is an expression that looks like a member access to a +/// destructor of a scalar type, except that scalar types don't have +/// destructors. For example: +/// +/// \code +/// typedef int T; +/// void f(int *p) { +/// p->T::~T(); +/// } +/// \endcode +/// +/// Pseudo-destructors typically occur when instantiating templates such as: +/// +/// \code +/// template<typename T> +/// void destroy(T* ptr) { +/// ptr->T::~T(); +/// } +/// \endcode +/// +/// for scalar types. A pseudo-destructor expression has no run-time semantics +/// beyond evaluating the base expression. +class CXXPseudoDestructorExpr : public Expr { + /// \brief The base expression (that is being destroyed). + Stmt *Base; + + /// \brief Whether the operator was an arrow ('->'); otherwise, it was a + /// period ('.'). + bool IsArrow : 1; + + /// \brief The location of the '.' or '->' operator. + SourceLocation OperatorLoc; + + /// \brief The nested-name-specifier that follows the operator, if present. + NestedNameSpecifier *Qualifier; + + /// \brief The source range that covers the nested-name-specifier, if + /// present. + SourceRange QualifierRange; + + /// \brief The type that precedes the '::' in a qualified pseudo-destructor + /// expression. + TypeSourceInfo *ScopeType; + + /// \brief The location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation ColonColonLoc; + + /// \brief The location of the '~'. + SourceLocation TildeLoc; + + /// \brief The type being destroyed, or its name if we were unable to + /// resolve the name. + PseudoDestructorTypeStorage DestroyedType; + +public: + CXXPseudoDestructorExpr(ASTContext &Context, + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType) + : Expr(CXXPseudoDestructorExprClass, + Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, + false, 0, false, + false, 0, 0, + FunctionType::ExtInfo())), + /*isTypeDependent=*/(Base->isTypeDependent() || + (DestroyedType.getTypeSourceInfo() && + DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), + /*isValueDependent=*/Base->isValueDependent()), + Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), + OperatorLoc(OperatorLoc), Qualifier(Qualifier), + QualifierRange(QualifierRange), + ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), + DestroyedType(DestroyedType) { } + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + /// \brief Determines whether this member expression actually had + /// a C++ nested-name-specifier prior to the name of the member, e.g., + /// x->Base::foo. + bool hasQualifier() const { return Qualifier != 0; } + + /// \brief If the member name was qualified, retrieves the source range of + /// the nested-name-specifier that precedes the member name. Otherwise, + /// returns an empty source range. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Determine whether this pseudo-destructor expression was written + /// using an '->' (otherwise, it used a '.'). + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '.' or '->' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// \brief Retrieve the scope type in a qualified pseudo-destructor + /// expression. + /// + /// Pseudo-destructor expressions can have extra qualification within them + /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). + /// Here, if the object type of the expression is (or may be) a scalar type, + /// \p T may also be a scalar type and, therefore, cannot be part of a + /// nested-name-specifier. It is stored as the "scope type" of the pseudo- + /// destructor expression. + TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } + + /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation getColonColonLoc() const { return ColonColonLoc; } + + /// \brief Retrieve the location of the '~'. + SourceLocation getTildeLoc() const { return TildeLoc; } + + /// \brief Retrieve the source location information for the type + /// being destroyed. + /// + /// This type-source information is available for non-dependent + /// pseudo-destructor expressions and some dependent pseudo-destructor + /// expressions. Returns NULL if we only have the identifier for a + /// dependent pseudo-destructor expression. + TypeSourceInfo *getDestroyedTypeInfo() const { + return DestroyedType.getTypeSourceInfo(); + } + + /// \brief In a dependent pseudo-destructor expression for which we do not + /// have full type information on the destroyed type, provides the name + /// of the destroyed type. + IdentifierInfo *getDestroyedTypeIdentifier() const { + return DestroyedType.getIdentifier(); + } + + /// \brief Retrieve the type being destroyed. + QualType getDestroyedType() const; + + /// \brief Retrieve the starting location of the type being destroyed. + SourceLocation getDestroyedTypeLoc() const { + return DestroyedType.getLocation(); + } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXPseudoDestructorExprClass; + } + static bool classof(const CXXPseudoDestructorExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the +/// implementation of TR1/C++0x type trait templates. +/// Example: +/// __is_pod(int) == true +/// __is_enum(std::string) == false +class UnaryTypeTraitExpr : public Expr { + /// UTT - The trait. + UnaryTypeTrait UTT; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// QueriedType - The type we're testing. + QualType QueriedType; + +public: + UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried, + SourceLocation rparen, QualType ty) + : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()), + UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + + UnaryTypeTrait getTrait() const { return UTT; } + + QualType getQueriedType() const { return QueriedType; } + + bool EvaluateTrait(ASTContext&) const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnaryTypeTraitExprClass; + } + static bool classof(const UnaryTypeTraitExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief A reference to an overloaded function set, either an +/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. +class OverloadExpr : public Expr { + /// The results. These are undesugared, which is to say, they may + /// include UsingShadowDecls. Access is relative to the naming + /// class. + // FIXME: Allocate this data after the OverloadExpr subclass. + DeclAccessPair *Results; + unsigned NumResults; + + /// The common name of these declarations. + DeclarationName Name; + + /// The scope specifier, if any. + NestedNameSpecifier *Qualifier; + + /// The source range of the scope specifier. + SourceRange QualifierRange; + + /// The location of the name. + SourceLocation NameLoc; + + /// True if the name was a template-id. + bool HasExplicitTemplateArgs; + +protected: + OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, + NestedNameSpecifier *Qualifier, SourceRange QRange, + DeclarationName Name, SourceLocation NameLoc, + bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + +public: + /// Computes whether an unresolved lookup on the given declarations + /// and optional template arguments is type- and value-dependent. + static bool ComputeDependence(UnresolvedSetIterator Begin, + UnresolvedSetIterator End, + const TemplateArgumentListInfo *Args); + + /// Finds the overloaded expression in the given expression of + /// OverloadTy. + /// + /// \return the expression (which must be there) and true if it is + /// within an address-of operator. + static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) { + assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); + + bool op = false; + E = E->IgnoreParens(); + if (isa<UnaryOperator>(E)) + op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); + return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); + } + + /// Gets the naming class of this lookup, if any. + CXXRecordDecl *getNamingClass() const; + + typedef UnresolvedSetImpl::iterator decls_iterator; + decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } + decls_iterator decls_end() const { + return UnresolvedSetIterator(Results + NumResults); + } + + /// Gets the number of declarations in the unresolved set. + unsigned getNumDecls() const { return NumResults; } + + /// Gets the name looked up. + DeclarationName getName() const { return Name; } + void setName(DeclarationName N) { Name = N; } + + /// Gets the location of the name. + SourceLocation getNameLoc() const { return NameLoc; } + void setNameLoc(SourceLocation Loc) { NameLoc = Loc; } + + /// Fetches the nested-name qualifier, if one was given. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// Fetches the range of the nested-name qualifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Determines whether this expression had an explicit + /// template argument list, e.g. f<int>. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + + ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below + + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); + } + + ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { + if (hasExplicitTemplateArgs()) + return &getExplicitTemplateArgs(); + return 0; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass || + T->getStmtClass() == UnresolvedMemberExprClass; + } + static bool classof(const OverloadExpr *) { return true; } +}; + +/// \brief A reference to a name which we were able to look up during +/// parsing but could not resolve to a specific declaration. This +/// arises in several ways: +/// * we might be waiting for argument-dependent lookup +/// * the name might resolve to an overloaded function +/// and eventually: +/// * the lookup might have included a function template +/// These never include UnresolvedUsingValueDecls, which are always +/// class members and therefore appear only in +/// UnresolvedMemberLookupExprs. +class UnresolvedLookupExpr : public OverloadExpr { + /// True if these lookup results should be extended by + /// argument-dependent lookup if this is the operand of a function + /// call. + bool RequiresADL; + + /// True if these lookup results are overloaded. This is pretty + /// trivially rederivable if we urgently need to kill this field. + bool Overloaded; + + /// The naming class (C++ [class.access.base]p5) of the lookup, if + /// any. This can generally be recalculated from the context chain, + /// but that can be fairly expensive for unqualified lookups. If we + /// want to improve memory use here, this could go in a union + /// against the qualified-lookup bits. + CXXRecordDecl *NamingClass; + + UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, + CXXRecordDecl *NamingClass, + NestedNameSpecifier *Qualifier, SourceRange QRange, + DeclarationName Name, SourceLocation NameLoc, + bool RequiresADL, bool Overloaded, bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End) + : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, + QRange, Name, NameLoc, HasTemplateArgs, Begin, End), + RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) + {} + +public: + static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, + CXXRecordDecl *NamingClass, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool ADL, bool Overloaded, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + return new(C) UnresolvedLookupExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, + Dependent, NamingClass, + Qualifier, QualifierRange, + Name, NameLoc, ADL, Overloaded, false, + Begin, End); + } + + static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, + CXXRecordDecl *NamingClass, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool ADL, + const TemplateArgumentListInfo &Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End); + + /// True if this declaration should be extended by + /// argument-dependent lookup. + bool requiresADL() const { return RequiresADL; } + + /// True if this lookup is overloaded. + bool isOverloaded() const { return Overloaded; } + + /// Gets the 'naming class' (in the sense of C++0x + /// [class.access.base]p5) of the lookup. This is the scope + /// 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. + + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1); + } + + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); + } + + /// \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; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range(getNameLoc()); + if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); + if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + return Range; + } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass; + } + static bool classof(const UnresolvedLookupExpr *) { return true; } +}; + +/// \brief A qualified reference to a name whose declaration cannot +/// yet be resolved. +/// +/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that +/// it expresses a reference to a declaration such as +/// X<T>::value. The difference, however, is that an +/// DependentScopeDeclRefExpr node is used only within C++ templates when +/// the qualification (e.g., X<T>::) refers to a dependent type. In +/// this case, X<T>::value cannot resolve to a declaration because the +/// declaration will differ from on instantiation of X<T> to the +/// next. Therefore, DependentScopeDeclRefExpr keeps track of the +/// qualifier (X<T>::) and the name of the entity being referenced +/// ("value"). Such expressions will instantiate to a DeclRefExpr once the +/// declaration can be found. +class DependentScopeDeclRefExpr : public Expr { + /// The name of the entity we will be referencing. + DeclarationName Name; + + /// Location of the name of the declaration we're referencing. + SourceLocation Loc; + + /// QualifierRange - The source range that covers the + /// nested-name-specifier. + SourceRange QualifierRange; + + /// \brief The nested-name-specifier that qualifies this unresolved + /// declaration name. + NestedNameSpecifier *Qualifier; + + /// \brief Whether the name includes explicit template arguments. + bool HasExplicitTemplateArgs; + + DependentScopeDeclRefExpr(QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool HasExplicitTemplateArgs) + : Expr(DependentScopeDeclRefExprClass, T, true, true), + Name(Name), Loc(NameLoc), + QualifierRange(QualifierRange), Qualifier(Qualifier), + HasExplicitTemplateArgs(HasExplicitTemplateArgs) + {} + +public: + static DependentScopeDeclRefExpr *Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs = 0); + + /// \brief Retrieve the name that this expression refers to. + DeclarationName getDeclName() const { return Name; } + + /// \brief Retrieve the location of the name within the expression. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the source range of the nested-name-specifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the nested-name-specifier that qualifies this + /// declaration. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. + + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); + } + + /// \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; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range(QualifierRange.getBegin(), getLocation()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + return Range; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DependentScopeDeclRefExprClass; + } + static bool classof(const DependentScopeDeclRefExpr *) { return true; } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); +}; + +class CXXExprWithTemporaries : public Expr { + Stmt *SubExpr; + + CXXTemporary **Temps; + unsigned NumTemps; + + CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, + unsigned NumTemps); + ~CXXExprWithTemporaries(); + +protected: + virtual void DoDestroy(ASTContext &C); + +public: + CXXExprWithTemporaries(EmptyShell Empty) + : Expr(CXXExprWithTemporariesClass, Empty), + SubExpr(0), Temps(0), NumTemps(0) {} + + static CXXExprWithTemporaries *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]; + } + const CXXTemporary *getTemporary(unsigned i) const { + return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i); + } + void setTemporary(unsigned i, CXXTemporary *T) { + assert(i < NumTemps && "Index out of range"); + Temps[i] = T; + } + + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + virtual SourceRange getSourceRange() const { + return SubExpr->getSourceRange(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXExprWithTemporariesClass; + } + static bool classof(const CXXExprWithTemporaries *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Describes an explicit type conversion that uses functional +/// notion but could not be resolved because one or more arguments are +/// type-dependent. +/// +/// The explicit type conversions expressed by +/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN), +/// where \c T is some type and \c a1, a2, ..., aN are values, and +/// either \C T is a dependent type or one or more of the \c a's is +/// type-dependent. For example, this would occur in a template such +/// as: +/// +/// \code +/// template<typename T, typename A1> +/// inline T make_a(const A1& a1) { +/// return T(a1); +/// } +/// \endcode +/// +/// When the returned expression is instantiated, it may resolve to a +/// constructor call, conversion function call, or some kind of type +/// conversion. +class CXXUnresolvedConstructExpr : public Expr { + /// \brief The starting location of the type + SourceLocation TyBeginLoc; + + /// \brief The type being constructed. + QualType Type; + + /// \brief The location of the left parentheses ('('). + SourceLocation LParenLoc; + + /// \brief The location of the right parentheses (')'). + SourceLocation RParenLoc; + + /// \brief The number of arguments used to construct the type. + unsigned NumArgs; + + CXXUnresolvedConstructExpr(SourceLocation TyBegin, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc); + +public: + static CXXUnresolvedConstructExpr *Create(ASTContext &C, + SourceLocation TyBegin, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc); + + /// \brief Retrieve the source location where the type begins. + SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } + void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + + /// \brief Retrieve the type that is being constructed, as specified + /// in the source code. + QualType getTypeAsWritten() const { return Type; } + void setTypeAsWritten(QualType T) { Type = T; } + + /// \brief Retrieve the location of the left parentheses ('(') that + /// precedes the argument list. + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + /// \brief Retrieve the location of the right parentheses (')') that + /// follows the argument list. + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + /// \brief Retrieve the number of arguments. + unsigned arg_size() const { return NumArgs; } + + typedef Expr** arg_iterator; + arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); } + arg_iterator arg_end() { return arg_begin() + NumArgs; } + + typedef const Expr* const * const_arg_iterator; + const_arg_iterator arg_begin() const { + return reinterpret_cast<const Expr* const *>(this + 1); + } + const_arg_iterator arg_end() const { + return arg_begin() + NumArgs; + } + + Expr *getArg(unsigned I) { + assert(I < NumArgs && "Argument index out-of-range"); + return *(arg_begin() + I); + } + + const Expr *getArg(unsigned I) const { + assert(I < NumArgs && "Argument index out-of-range"); + return *(arg_begin() + I); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(TyBeginLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUnresolvedConstructExprClass; + } + static bool classof(const CXXUnresolvedConstructExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Represents a C++ member access expression where the actual +/// member referenced could not be resolved because the base +/// expression or the member name was dependent. +/// +/// Like UnresolvedMemberExprs, these can be either implicit or +/// explicit accesses. It is only possible to get one of these with +/// an implicit access if a qualifier is provided. +class CXXDependentScopeMemberExpr : public Expr { + /// \brief The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. Can be null in implicit accesses. + Stmt *Base; + + /// \brief The type of the base expression. Never null, even for + /// implicit accesses. + QualType BaseType; + + /// \brief Whether this member expression used the '->' operator or + /// the '.' operator. + bool IsArrow : 1; + + /// \brief Whether this member expression has explicitly-specified template + /// arguments. + bool HasExplicitTemplateArgs : 1; + + /// \brief The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + + /// \brief The nested-name-specifier that precedes the member name, if any. + NestedNameSpecifier *Qualifier; + + /// \brief The source range covering the nested name specifier. + SourceRange QualifierRange; + + /// \brief In a qualified member access expression such as t->Base::f, this + /// member stores the resolves of name lookup in the context of the member + /// access expression, to be used at instantiation time. + /// + /// FIXME: This member, along with the Qualifier and QualifierRange, could + /// be stuck into a structure that is optionally allocated at the end of + /// the CXXDependentScopeMemberExpr, to save space in the common case. + NamedDecl *FirstQualifierFoundInScope; + + /// \brief The member to which this member expression refers, which + /// can be name, overloaded operator, or destructor. + /// FIXME: could also be a template-id + DeclarationName Member; + + /// \brief The location of the member name. + SourceLocation MemberLoc; + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + assert(HasExplicitTemplateArgs); + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<CXXDependentScopeMemberExpr *>(this) + ->getExplicitTemplateArgumentList(); + } + + CXXDependentScopeMemberExpr(ASTContext &C, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs); + +public: + CXXDependentScopeMemberExpr(ASTContext &C, + Expr *Base, QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc) + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), + Qualifier(Qualifier), QualifierRange(QualifierRange), + FirstQualifierFoundInScope(FirstQualifierFoundInScope), + Member(Member), MemberLoc(MemberLoc) { } + + static CXXDependentScopeMemberExpr * + Create(ASTContext &C, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs); + + /// \brief True if this is an implicit access, i.e. one in which the + /// member being accessed was not written in the source. The source + /// location of the operator is invalid in this case. + bool isImplicitAccess() const { return Base == 0; } + + /// \brief Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + void setBase(Expr *E) { Base = E; } + + QualType getBaseType() const { return BaseType; } + + /// \brief Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Retrieve the source range covering the nested-name-specifier + /// that qualifies the member name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \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. + /// + /// This function only returns a useful result when member access expression + /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration + /// returned by this function describes what was found by unqualified name + /// lookup for the identifier "Base" within the scope of the member access + /// expression itself. At template instantiation time, this information is + /// combined with the results of name lookup into the type of the object + /// expression itself (the class type of x). + NamedDecl *getFirstQualifierFoundInScope() const { + return FirstQualifierFoundInScope; + } + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMember() const { return Member; } + void setMember(DeclarationName N) { Member = N; } + + // \brief Retrieve the location of the name of the member that this + // expression refers to. + SourceLocation getMemberLoc() const { return MemberLoc; } + void setMemberLoc(SourceLocation L) { MemberLoc = L; } + + /// \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; + } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + assert(HasExplicitTemplateArgs); + getExplicitTemplateArgumentList()->copyInto(List); + } + + /// \brief Retrieve the location of the left angle bracket following the + /// member name ('<'), if any. + SourceLocation getLAngleLoc() const { + assert(HasExplicitTemplateArgs); + return getExplicitTemplateArgumentList()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + assert(HasExplicitTemplateArgs); + return getExplicitTemplateArgumentList()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + assert(HasExplicitTemplateArgs); + return getExplicitTemplateArgumentList()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { + assert(HasExplicitTemplateArgs); + return getExplicitTemplateArgumentList()->RAngleLoc; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range; + if (!isImplicitAccess()) + Range.setBegin(Base->getSourceRange().getBegin()); + else if (getQualifier()) + Range.setBegin(getQualifierRange().getBegin()); + else + Range.setBegin(MemberLoc); + + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + else + Range.setEnd(MemberLoc); + return Range; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDependentScopeMemberExprClass; + } + static bool classof(const CXXDependentScopeMemberExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Represents a C++ member access expression for which lookup +/// produced a set of overloaded functions. +/// +/// The member access may be explicit or implicit: +/// struct A { +/// int a, b; +/// int explicitAccess() { return this->a + this->A::b; } +/// int implicitAccess() { return a + A::b; } +/// }; +/// +/// In the final AST, an explicit access always becomes a MemberExpr. +/// An implicit access may become either a MemberExpr or a +/// DeclRefExpr, depending on whether the member is static. +class UnresolvedMemberExpr : public OverloadExpr { + /// \brief Whether this member expression used the '->' operator or + /// the '.' operator. + bool IsArrow : 1; + + /// \brief Whether the lookup results contain an unresolved using + /// declaration. + bool HasUnresolvedUsing : 1; + + /// \brief The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. This can be null if this is an 'unbased' + /// member expression + Stmt *Base; + + /// \brief The type of the base expression; never null. + QualType BaseType; + + /// \brief The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + + UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + +public: + static UnresolvedMemberExpr * + Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + /// \brief True if this is an implicit access, i.e. one in which the + /// member being accessed was not written in the source. The source + /// location of the operator is invalid in this case. + bool isImplicitAccess() const { return Base == 0; } + + /// \brief Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + const Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + void setBase(Expr *E) { Base = E; } + + QualType getBaseType() const { return BaseType; } + + /// \brief Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Retrieves the naming class of this lookup. + CXXRecordDecl *getNamingClass() const; + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMemberName() const { return getName(); } + void setMemberName(DeclarationName N) { setName(N); } + + // \brief Retrieve the location of the name of the member that this + // expression refers to. + SourceLocation getMemberLoc() const { return getNameLoc(); } + void setMemberLoc(SourceLocation L) { setNameLoc(L); } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1); + } + + /// \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; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range; + if (!isImplicitAccess()) + Range.setBegin(Base->getSourceRange().getBegin()); + else if (getQualifier()) + Range.setBegin(getQualifierRange().getBegin()); + else + Range.setBegin(getMemberLoc()); + + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + else + Range.setEnd(getMemberLoc()); + return Range; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedMemberExprClass; + } + static bool classof(const UnresolvedMemberExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() { + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs(); + else + return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs(); +} + +} // 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 new file mode 100644 index 0000000..8a09f4e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h @@ -0,0 +1,815 @@ +//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 ExprObjC interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPROBJC_H +#define LLVM_CLANG_AST_EXPROBJC_H + +#include "clang/AST/Expr.h" +#include "clang/Basic/IdentifierTable.h" + +namespace clang { + class IdentifierInfo; + class ASTContext; + class ObjCMethodDecl; + class ObjCPropertyDecl; + +/// ObjCStringLiteral, used for Objective-C string literals +/// i.e. @"foo". +class ObjCStringLiteral : public Expr { + Stmt *String; + SourceLocation AtLoc; +public: + ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) + : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {} + explicit ObjCStringLiteral(EmptyShell Empty) + : Expr(ObjCStringLiteralClass, Empty) {} + + StringLiteral *getString() { return cast<StringLiteral>(String); } + const StringLiteral *getString() const { return cast<StringLiteral>(String); } + void setString(StringLiteral *S) { String = S; } + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, String->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCStringLiteralClass; + } + static bool classof(const ObjCStringLiteral *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// 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. +class ObjCEncodeExpr : public Expr { + TypeSourceInfo *EncodedType; + SourceLocation AtLoc, RParenLoc; +public: + ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, + SourceLocation at, SourceLocation rp) + : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(), + EncodedType->getType()->isDependentType()), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} + + explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} + + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + QualType getEncodedType() const { return EncodedType->getType(); } + + TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } + void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { + EncodedType = EncType; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCEncodeExprClass; + } + static bool classof(const ObjCEncodeExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCSelectorExpr used for @selector in Objective-C. +class ObjCSelectorExpr : public Expr { + Selector SelName; + SourceLocation AtLoc, RParenLoc; +public: + ObjCSelectorExpr(QualType T, Selector selInfo, + SourceLocation at, SourceLocation rp) + : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at), + RParenLoc(rp){} + explicit ObjCSelectorExpr(EmptyShell Empty) + : Expr(ObjCSelectorExprClass, Empty) {} + + Selector getSelector() const { return SelName; } + void setSelector(Selector S) { SelName = S; } + + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, RParenLoc); + } + + /// getNumArgs - Return the number of actual arguments to this call. + unsigned getNumArgs() const { return SelName.getNumArgs(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSelectorExprClass; + } + static bool classof(const ObjCSelectorExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used +/// as: @protocol(foo), as in: +/// obj conformsToProtocol:@protocol(foo)] +/// The return type is "Protocol*". +class ObjCProtocolExpr : public Expr { + ObjCProtocolDecl *TheProtocol; + SourceLocation AtLoc, RParenLoc; +public: + ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, + SourceLocation at, SourceLocation rp) + : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol), + AtLoc(at), RParenLoc(rp) {} + explicit ObjCProtocolExpr(EmptyShell Empty) + : Expr(ObjCProtocolExprClass, Empty) {} + + ObjCProtocolDecl *getProtocol() const { return TheProtocol; } + void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } + + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCProtocolExprClass; + } + static bool classof(const ObjCProtocolExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCIvarRefExpr - A reference to an ObjC instance variable. +class ObjCIvarRefExpr : public Expr { + class ObjCIvarDecl *D; + SourceLocation Loc; + Stmt *Base; + 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). + +public: + ObjCIvarRefExpr(ObjCIvarDecl *d, + QualType t, SourceLocation l, Expr *base, + bool arrow = false, bool freeIvar = false) : + Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), D(d), + Loc(l), Base(base), IsArrow(arrow), + IsFreeIvar(freeIvar) {} + + explicit ObjCIvarRefExpr(EmptyShell Empty) + : Expr(ObjCIvarRefExprClass, Empty) {} + + ObjCIvarDecl *getDecl() { return D; } + const ObjCIvarDecl *getDecl() const { return D; } + void setDecl(ObjCIvarDecl *d) { D = d; } + + const Expr *getBase() const { return cast<Expr>(Base); } + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr * base) { Base = base; } + + bool isArrow() const { return IsArrow; } + bool isFreeIvar() const { return IsFreeIvar; } + void setIsArrow(bool A) { IsArrow = A; } + void setIsFreeIvar(bool A) { IsFreeIvar = A; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { + return isFreeIvar() ? SourceRange(Loc) + : SourceRange(getBase()->getLocStart(), Loc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIvarRefExprClass; + } + static bool classof(const ObjCIvarRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC +/// property. +/// +class ObjCPropertyRefExpr : public Expr { +private: + ObjCPropertyDecl *AsProperty; + SourceLocation IdLoc; + Stmt *Base; +public: + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, + SourceLocation l, Expr *base) + : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), + AsProperty(PD), IdLoc(l), Base(base) { + } + + explicit ObjCPropertyRefExpr(EmptyShell Empty) + : Expr(ObjCPropertyRefExprClass, Empty) {} + + ObjCPropertyDecl *getProperty() const { return AsProperty; } + void setProperty(ObjCPropertyDecl *D) { AsProperty = D; } + + const Expr *getBase() const { return cast<Expr>(Base); } + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr *base) { Base = base; } + + SourceLocation getLocation() const { return IdLoc; } + void setLocation(SourceLocation L) { IdLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), IdLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCPropertyRefExprClass; + } + static bool classof(const ObjCPropertyRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two +/// methods; one to set a value to an 'ivar' (Setter) and the other to access +/// an 'ivar' (Setter). +/// An example for use of this AST is: +/// @code +/// @interface Test { } +/// - (Test *)crash; +/// - (void)setCrash: (Test*)value; +/// @end +/// void foo(Test *p1, Test *p2) +/// { +/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST +/// } +/// @endcode +class ObjCImplicitSetterGetterRefExpr : public Expr { + /// Setter - Setter method user declared for setting its 'ivar' to a value + ObjCMethodDecl *Setter; + /// Getter - Getter method user declared for accessing 'ivar' it controls. + ObjCMethodDecl *Getter; + /// Location of the member in the dot syntax notation. This is location + /// of the getter method. + SourceLocation MemberLoc; + // FIXME: Swizzle these into a single pointer. + Stmt *Base; + ObjCInterfaceDecl *InterfaceDecl; + /// Location of the receiver class in the dot syntax notation + /// used to call a class method setter/getter. + SourceLocation ClassLoc; + +public: + ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, + QualType t, + ObjCMethodDecl *setter, + SourceLocation l, Expr *base) + : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), + Setter(setter), Getter(getter), MemberLoc(l), Base(base), + InterfaceDecl(0), ClassLoc(SourceLocation()) { + } + ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, + QualType t, + ObjCMethodDecl *setter, + SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) + : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), + Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), + ClassLoc(CL) { + } + explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty) + : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){} + + ObjCMethodDecl *getGetterMethod() const { return Getter; } + ObjCMethodDecl *getSetterMethod() const { return Setter; } + ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; } + void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } + void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } + void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; } + + virtual SourceRange getSourceRange() const { + if (Base) + return SourceRange(getBase()->getLocStart(), MemberLoc); + return SourceRange(ClassLoc, MemberLoc); + } + const Expr *getBase() const { return cast_or_null<Expr>(Base); } + Expr *getBase() { return cast_or_null<Expr>(Base); } + void setBase(Expr *base) { Base = base; } + + SourceLocation getLocation() const { return MemberLoc; } + void setLocation(SourceLocation L) { MemberLoc = L; } + SourceLocation getClassLoc() const { return ClassLoc; } + void setClassLoc(SourceLocation L) { ClassLoc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass; + } + static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief An expression that sends a message to the given Objective-C +/// object or class. +/// +/// The following contains two message send expressions: +/// +/// \code +/// [[NSString alloc] initWithString:@"Hello"] +/// \endcode +/// +/// The innermost message send invokes the "alloc" class method on the +/// NSString class, while the outermost message send invokes the +/// "initWithString" instance method on the object returned from +/// NSString's "alloc". In all, an Objective-C message send can take +/// on four different (although related) forms: +/// +/// 1. Send to an object instance. +/// 2. Send to a class. +/// 3. Send to the superclass instance of the current class. +/// 4. Send to the superclass of the current class. +/// +/// All four kinds of message sends are modeled by the ObjCMessageExpr +/// class, and can be distinguished via \c getReceiverKind(). Example: +/// +class ObjCMessageExpr : public Expr { + /// \brief The number of arguments in the message send, not + /// including the receiver. + unsigned NumArgs : 16; + + /// \brief The kind of message send this is, which is one of the + /// ReceiverKind values. + /// + /// We pad this out to a byte to avoid excessive masking and shifting. + unsigned Kind : 8; + + /// \brief Whether we have an actual method prototype in \c + /// SelectorOrMethod. + /// + /// When non-zero, we have a method declaration; otherwise, we just + /// have a selector. + unsigned HasMethod : 8; + + /// \brief When the message expression is a send to 'super', this is + /// the location of the 'super' keyword. + SourceLocation SuperLoc; + + /// \brief Stores either the selector that this message is sending + /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer + /// referring to the method that we type-checked against. + uintptr_t SelectorOrMethod; + + /// \brief The source locations of the open and close square + /// brackets ('[' and ']', respectively). + SourceLocation LBracLoc, RBracLoc; + + ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), + HasMethod(0), SelectorOrMethod(0) { } + + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Retrieve the pointer value of the message receiver. + void *getReceiverPointer() const { + return *const_cast<void **>( + reinterpret_cast<const void * const*>(this + 1)); + } + + /// \brief Set the pointer value of the message receiver. + void setReceiverPointer(void *Value) { + *reinterpret_cast<void **>(this + 1) = Value; + } + +public: + /// \brief The kind of receiver this message is sending to. + enum ReceiverKind { + /// \brief The receiver is a class. + Class = 0, + /// \brief The receiver is an object instance. + Instance, + /// \brief The receiver is a superclass. + SuperClass, + /// \brief The receiver is the instance of the superclass object. + SuperInstance + }; + + /// \brief Create a message send to super. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param SuperLoc The location of the "super" keyword. + /// + /// \param IsInstanceSuper Whether this is an instance "super" + /// message (otherwise, it's a class "super" message). + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create a class message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The type of the receiver, including + /// source-location information. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an instance message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The expression used to produce the object that + /// will receive this message. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an empty Objective-C message expression, to be + /// filled in by subsequent calls. + /// + /// \param Context The context in which the message send will be created. + /// + /// \param NumArgs The number of message arguments, not including + /// the receiver. + static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs); + + /// \brief Determine the kind of receiver that this message is being + /// sent to. + ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + + /// \brief Determine whether this is an instance message to either a + /// computed object or to super. + bool isInstanceMessage() const { + return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; + } + + /// \brief Determine whether this is an class message to either a + /// specified class or to super. + bool isClassMessage() const { + return getReceiverKind() == Class || getReceiverKind() == SuperClass; + } + + /// \brief Returns the receiver of an instance message. + /// + /// \brief Returns the object expression for an instance message, or + /// NULL for a message that is not an instance message. + Expr *getInstanceReceiver() { + if (getReceiverKind() == Instance) + return static_cast<Expr *>(getReceiverPointer()); + + return 0; + } + const Expr *getInstanceReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); + } + + /// \brief Turn this message send into an instance message that + /// computes the receiver object with the given expression. + void setInstanceReceiver(Expr *rec) { + Kind = Instance; + setReceiverPointer(rec); + } + + /// \brief Returns the type of a class message send, or NULL if the + /// message is not a class message. + QualType getClassReceiver() const { + if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) + return TSInfo->getType(); + + return QualType(); + } + + /// \brief Returns a type-source information of a class message + /// send, or NULL if the message is not a class message. + TypeSourceInfo *getClassReceiverTypeInfo() const { + if (getReceiverKind() == Class) + return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); + return 0; + } + + void setClassReceiver(TypeSourceInfo *TSInfo) { + Kind = Class; + setReceiverPointer(TSInfo); + } + + /// \brief Retrieve the location of the 'super' keyword for a class + /// or instance message to 'super', otherwise an invalid source location. + SourceLocation getSuperLoc() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return SuperLoc; + + return SourceLocation(); + } + + /// \brief Retrieve the Objective-C interface to which this message + /// is being directed, if known. + /// + /// This routine cross-cuts all of the different kinds of message + /// sends to determine what the underlying (statically known) type + /// of the receiver will be; use \c getReceiverKind() to determine + /// whether the message is a class or an instance method, whether it + /// is a send to super or not, etc. + /// + /// \returns The Objective-C interface if known, otherwise NULL. + ObjCInterfaceDecl *getReceiverInterface() const; + + /// \brief Retrieve the type referred to by 'super'. + /// + /// The returned type will either be an ObjCInterfaceType (for an + /// class message to super) or an ObjCObjectPointerType that refers + /// to a class (for an instance message to super); + QualType getSuperType() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return QualType::getFromOpaquePtr(getReceiverPointer()); + + return QualType(); + } + + void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { + Kind = IsInstanceSuper? SuperInstance : SuperClass; + SuperLoc = Loc; + setReceiverPointer(T.getAsOpaquePtr()); + } + + Selector getSelector() const; + + void setSelector(Selector S) { + HasMethod = false; + SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); + } + + const ObjCMethodDecl *getMethodDecl() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); + + return 0; + } + + ObjCMethodDecl *getMethodDecl() { + if (HasMethod) + return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); + + return 0; + } + + void setMethodDecl(ObjCMethodDecl *MD) { + HasMethod = true; + SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); + } + + /// \brief Return the number of actual arguments in this message, + /// not counting the receiver. + unsigned getNumArgs() const { return NumArgs; } + + /// \brief Retrieve the arguments to this message, not including the + /// receiver. + Stmt **getArgs() { + return reinterpret_cast<Stmt **>(this + 1) + 1; + } + const Stmt * const *getArgs() const { + return reinterpret_cast<const Stmt * const *>(this + 1) + 1; + } + + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(getArgs()[Arg]); + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return cast<Expr>(getArgs()[Arg]); + } + /// setArg - Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < NumArgs && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; + } + + SourceLocation getLeftLoc() const { return LBracLoc; } + SourceLocation getRightLoc() const { return RBracLoc; } + + void setLeftLoc(SourceLocation L) { LBracLoc = L; } + void setRightLoc(SourceLocation L) { RBracLoc = L; } + + void setSourceRange(SourceRange R) { + LBracLoc = R.getBegin(); + RBracLoc = R.getEnd(); + } + virtual SourceRange getSourceRange() const { + return SourceRange(LBracLoc, RBracLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCMessageExprClass; + } + static bool classof(const ObjCMessageExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + typedef ExprIterator arg_iterator; + typedef ConstExprIterator const_arg_iterator; + + arg_iterator arg_begin() { return getArgs(); } + arg_iterator arg_end() { return getArgs() + NumArgs; } + const_arg_iterator arg_begin() const { return getArgs(); } + const_arg_iterator arg_end() const { return getArgs() + NumArgs; } +}; + +/// ObjCSuperExpr - Represents the "super" expression in Objective-C, +/// which refers to the object on which the current method is executing. +/// +/// FIXME: This class is intended for removal, once its remaining +/// clients have been altered to represent "super" internally. +class ObjCSuperExpr : public Expr { + SourceLocation Loc; +public: + ObjCSuperExpr(SourceLocation L, QualType Type) + : Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { } + explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {} + + SourceLocation getLoc() const { return Loc; } + void setLoc(SourceLocation L) { Loc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSuperExprClass; + } + static bool classof(const ObjCSuperExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. +/// (similiar in spirit to MemberExpr). +class ObjCIsaExpr : public Expr { + /// Base - the expression for the base object pointer. + Stmt *Base; + + /// IsaMemberLoc - This is the location of the 'isa'. + SourceLocation IsaMemberLoc; + + /// IsArrow - True if this is "X->F", false if this is "X.F". + bool IsArrow; +public: + ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) + : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false, + base->isValueDependent()), + Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} + + /// \brief Build an empty expression. + explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } + + void setBase(Expr *E) { Base = E; } + Expr *getBase() const { return cast<Expr>(Base); } + + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// getMemberLoc - Return the location of the "member", in X->F, it is the + /// location of 'F'. + SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } + void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), IsaMemberLoc); + } + + virtual SourceLocation getExprLoc() const { return IsaMemberLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIsaExprClass; + } + static bool classof(const ObjCIsaExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h new file mode 100644 index 0000000..79e4451 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h @@ -0,0 +1,192 @@ +//===--- ExternalASTSource.h - Abstract External AST Interface --*- 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 ExternalASTSource interface, which enables +// construction of AST nodes from some external source.x +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H + +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> +#include <vector> +namespace clang { + +class ASTConsumer; +class Decl; +class DeclContext; +class ExternalSemaSource; // layering violation required for downcasting +class Stmt; + +/// \brief The deserialized representation of a set of declarations +/// with the same name that are visible in a given context. +struct VisibleDeclaration { + /// \brief The name of the declarations. + DeclarationName Name; + + /// \brief The ID numbers of all of the declarations with this name. + /// + /// These declarations have not necessarily been de-serialized. + llvm::SmallVector<unsigned, 4> Declarations; +}; + +/// \brief Abstract interface for external sources of AST nodes. +/// +/// External AST sources provide AST nodes constructed from some +/// external source, such as a precompiled header. External AST +/// sources can resolve types and declarations from abstract IDs into +/// actual type and declaration nodes, and read parts of declaration +/// contexts. +class ExternalASTSource { + /// \brief Whether this AST source also provides information for + /// semantic analysis. + bool SemaSource; + + friend class ExternalSemaSource; + +public: + ExternalASTSource() : SemaSource(false) { } + + virtual ~ExternalASTSource(); + + /// \brief Resolve a type ID into a type, potentially building a new + /// type. + virtual QualType GetType(uint32_t ID) = 0; + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + virtual Decl *GetDecl(uint32_t ID) = 0; + + /// \brief Resolve a selector ID into a selector. + virtual Selector GetSelector(uint32_t ID) = 0; + + /// \brief Returns the number of selectors known to the external AST + /// source. + virtual uint32_t GetNumKnownSelectors() = 0; + + /// \brief Resolve the offset of a statement in the decl stream into a + /// statement. + /// + /// This operation will read a new statement from the external + /// source each time it is called, and is meant to be used via a + /// LazyOffsetPtr. + virtual Stmt *GetDeclStmt(uint64_t Offset) = 0; + + /// \brief Read all of the declarations lexically stored in a + /// declaration context. + /// + /// \param DC The declaration context whose declarations will be + /// read. + /// + /// \param Decls Vector that will contain the declarations loaded + /// from the external source. The caller is responsible for merging + /// these declarations with any declarations already stored in the + /// declaration context. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, + llvm::SmallVectorImpl<uint32_t> &Decls) = 0; + + /// \brief Read all of the declarations visible from a declaration + /// context. + /// + /// \param DC The declaration context whose visible declarations + /// will be read. + /// + /// \param Decls A vector of visible declaration structures, + /// providing the mapping from each name visible in the declaration + /// context to the declaration IDs of declarations with that name. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsVisibleInContext(DeclContext *DC, + llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0; + + /// \brief Function that will be invoked when we begin parsing a new + /// translation unit involving this external AST source. + virtual void StartTranslationUnit(ASTConsumer *Consumer) { } + + /// \brief Print any statistics that have been gathered regarding + /// the external AST source. + virtual void PrintStats(); +}; + +/// \brief A lazy pointer to an AST node (of base type T) that resides +/// within an external AST source. +/// +/// The AST node is identified within the external AST source by a +/// 63-bit offset, and can be retrieved via an operation on the +/// external AST source itself. +template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)> +struct LazyOffsetPtr { + /// \brief Either a pointer to an AST node or the offset within the + /// external AST source where the AST node can be found. + /// + /// If the low bit is clear, a pointer to the AST node. If the low + /// bit is set, the upper 63 bits are the offset. + mutable uint64_t Ptr; + +public: + LazyOffsetPtr() : Ptr(0) { } + + explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } + explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { + assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); + if (Offset == 0) + Ptr = 0; + } + + LazyOffsetPtr &operator=(T *Ptr) { + this->Ptr = reinterpret_cast<uint64_t>(Ptr); + return *this; + } + + LazyOffsetPtr &operator=(uint64_t Offset) { + assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); + if (Offset == 0) + Ptr = 0; + else + Ptr = (Offset << 1) | 0x01; + + return *this; + } + + /// \brief Whether this pointer is non-NULL. + /// + /// This operation does not require the AST node to be deserialized. + operator bool() const { return Ptr != 0; } + + /// \brief Whether this pointer is currently stored as an offset. + bool isOffset() const { return Ptr & 0x01; } + + /// \brief Retrieve the pointer to the AST node that this lazy pointer + /// + /// \param Source the external AST source. + /// + /// \returns a pointer to the AST node. + T* get(ExternalASTSource *Source) const { + if (isOffset()) { + assert(Source && + "Cannot deserialize a lazy pointer without an AST source"); + Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); + } + return reinterpret_cast<T*>(Ptr); + } +}; + +/// \brief A lazy pointer to a statement. +typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/FullExpr.h b/contrib/llvm/tools/clang/include/clang/AST/FullExpr.h new file mode 100644 index 0000000..bb81bf0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/FullExpr.h @@ -0,0 +1,89 @@ +//===--- FullExpr.h - C++ full expression 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 FullExpr interface, to be used for type safe handling +// of full expressions. +// +// Full expressions are described in C++ [intro.execution]p12. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_FULLEXPR_H +#define LLVM_CLANG_AST_FULLEXPR_H + +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + class ASTContext; + class CXXTemporary; + class Expr; + +class FullExpr { + struct ExprAndTemporaries { + Expr *SubExpr; + + unsigned NumTemps; + + typedef CXXTemporary** temps_iterator; + + temps_iterator temps_begin() { + return reinterpret_cast<CXXTemporary **>(this + 1); + } + temps_iterator temps_end() { + return temps_begin() + NumTemps; + } + }; + + typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy; + SubExprTy SubExpr; + + FullExpr() { } + +public: + static FullExpr Create(ASTContext &Context, Expr *SubExpr, + CXXTemporary **Temps, unsigned NumTemps); + void Destroy(ASTContext &Context); + + Expr *getExpr() { + if (Expr *E = SubExpr.dyn_cast<Expr *>()) + return E; + + return SubExpr.get<ExprAndTemporaries *>()->SubExpr; + } + + const Expr *getExpr() const { + return const_cast<FullExpr*>(this)->getExpr(); + } + + typedef CXXTemporary** temps_iterator; + + temps_iterator temps_begin() { + if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) + return ET->temps_begin(); + + return 0; + } + temps_iterator temps_end() { + if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) + return ET->temps_end(); + + return 0; + } + + void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); } + + static FullExpr getFromOpaquePtr(void *Ptr) { + FullExpr E; + E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr); + return E; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Makefile b/contrib/llvm/tools/clang/include/clang/AST/Makefile new file mode 100644 index 0000000..a25977c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Makefile @@ -0,0 +1,13 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = StmtNodes.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +INPUT_TDS = $(PROJ_SRC_DIR)/StmtNodes.td + +$(ObjDir)/StmtNodes.inc.tmp : StmtNodes.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang statement node tables with tblgen" + $(Verb) $(TableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< + diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h new file mode 100644 index 0000000..1594b09 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h @@ -0,0 +1,202 @@ +//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- 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 NestedNameSpecifier class, which represents +// a C++ nested-name-specifier. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H +#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class ASTContext; +class NamespaceDecl; +class IdentifierInfo; +struct PrintingPolicy; +class Type; +class LangOptions; + +/// \brief Represents a C++ nested name specifier, such as +/// "::std::vector<int>::". +/// +/// C++ nested name specifiers are the prefixes to qualified +/// 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). +class NestedNameSpecifier : public llvm::FoldingSetNode { + /// \brief The nested name specifier that precedes this nested name + /// specifier. + /// + /// The pointer is the nested-name-specifier that precedes this + /// one. The integer stores one of the first four values of type + /// SpecifierKind. + llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix; + + /// \brief The last component in the nested name specifier, which + /// can be an identifier, a declaration, or a type. + /// + /// When the pointer is NULL, this specifier represents the global + /// specifier '::'. Otherwise, the pointer is one of + /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of + /// specifier as encoded within the prefix. + void* Specifier; + +public: + /// \brief The kind of specifier that completes this nested name + /// specifier. + enum SpecifierKind { + /// \brief An identifier, stored as an IdentifierInfo*. + Identifier = 0, + /// \brief A namespace, stored as a Namespace*. + Namespace = 1, + /// \brief A type, stored as a Type*. + TypeSpec = 2, + /// \brief A type that was preceded by the 'template' keyword, + /// stored as a Type*. + TypeSpecWithTemplate = 3, + /// \brief The global specifier '::'. There is no stored value. + Global = 4 + }; + +private: + /// \brief Builds the global specifier. + NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { } + + /// \brief Copy constructor used internally to clone nested name + /// specifiers. + NestedNameSpecifier(const NestedNameSpecifier &Other) + : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), + Specifier(Other.Specifier) { + } + + NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement + + /// \brief Either find or insert the given nested name specifier + /// mockup in the given context. + static NestedNameSpecifier *FindOrInsert(ASTContext &Context, + const NestedNameSpecifier &Mockup); + +public: + /// \brief Builds a specifier combining a prefix and an identifier. + /// + /// The prefix must be dependent, since nested name specifiers + /// referencing an identifier are only permitted when the identifier + /// cannot be resolved. + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, + IdentifierInfo *II); + + /// \brief Builds a nested name specifier that names a namespace. + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, + NamespaceDecl *NS); + + /// \brief Builds a nested name specifier that names a type. + static NestedNameSpecifier *Create(ASTContext &Context, + NestedNameSpecifier *Prefix, + bool Template, Type *T); + + /// \brief Builds a specifier that consists of just an identifier. + /// + /// The nested-name-specifier is assumed to be dependent, but has no + /// prefix because the prefix is implied by something outside of the + /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent + /// type. + static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II); + + /// \brief Returns the nested name specifier representing the global + /// scope. + static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context); + + /// \brief Return the prefix of this nested name specifier. + /// + /// The prefix contains all of the parts of the nested name + /// specifier that preced this current specifier. For example, for a + /// nested name specifier that represents "foo::bar::", the current + /// specifier will contain "bar::" and the prefix will contain + /// "foo::". + NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } + + /// \brief Determine what kind of nested name specifier is stored. + SpecifierKind getKind() const { + if (Specifier == 0) + return Global; + return (SpecifierKind)Prefix.getInt(); + } + + /// \brief Retrieve the identifier stored in this nested name + /// specifier. + IdentifierInfo *getAsIdentifier() const { + if (Prefix.getInt() == Identifier) + return (IdentifierInfo *)Specifier; + + return 0; + } + + /// \brief Retrieve the namespace stored in this nested name + /// specifier. + NamespaceDecl *getAsNamespace() const { + if (Prefix.getInt() == Namespace) + return (NamespaceDecl *)Specifier; + + return 0; + } + + /// \brief Retrieve the type stored in this nested name specifier. + Type *getAsType() const { + if (Prefix.getInt() == TypeSpec || + Prefix.getInt() == TypeSpecWithTemplate) + return (Type *)Specifier; + + return 0; + } + + /// \brief Whether this nested name specifier refers to a dependent + /// type or not. + bool isDependent() const; + + /// \brief Print this nested name specifier to the given output + /// stream. + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(Prefix.getOpaqueValue()); + ID.AddPointer(Specifier); + } + + void Destroy(ASTContext &Context); + + /// \brief Dump the nested name specifier to standard output to aid + /// in debugging. + void dump(const LangOptions &LO); +}; + +/// 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), + Diagnostic::ak_nestednamespec); + return DB; +} + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h new file mode 100644 index 0000000..f826e11 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h @@ -0,0 +1,50 @@ +//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- 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 ParentMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARENTMAP_H +#define LLVM_CLANG_PARENTMAP_H + +namespace clang { +class Stmt; +class Expr; + +class ParentMap { + void* Impl; +public: + ParentMap(Stmt* ASTRoot); + ~ParentMap(); + + Stmt *getParent(Stmt*) const; + Stmt *getParentIgnoreParens(Stmt *) const; + + const Stmt *getParent(const Stmt* S) const { + return getParent(const_cast<Stmt*>(S)); + } + + const Stmt *getParentIgnoreParens(const Stmt *S) const { + return getParentIgnoreParens(const_cast<Stmt*>(S)); + } + + bool hasParent(Stmt* S) const { + return getParent(S) != 0; + } + + bool isConsumedExpr(Expr *E) const; + + bool isConsumedExpr(const Expr *E) const { + return isConsumedExpr(const_cast<Expr*>(E)); + } +}; + +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h new file mode 100644 index 0000000..70d65d3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h @@ -0,0 +1,110 @@ +//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- 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 PrinterHelper interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H +#define LLVM_CLANG_AST_PRETTY_PRINTER_H + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class Stmt; +class TagDecl; +class LangOptions; + +class PrinterHelper { +public: + virtual ~PrinterHelper(); + virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0; +}; + +/// \brief Describes how types, statements, expressions, and +/// declarations should be printed. +struct PrintingPolicy { + /// \brief Create a default printing policy for C. + PrintingPolicy(const LangOptions &LO) + : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), + SuppressTag(false), SuppressScope(false), + Dump(false), ConstantArraySizeAsWritten(false), + AnonymousTagLocations(true) { } + + /// \brief The number of spaces to use to indent each line. + unsigned Indentation : 8; + + /// \brief What language we're printing. + const LangOptions &LangOpts; + + /// \brief Whether we should suppress printing of the actual specifiers for + /// the given type or declaration. + /// + /// This flag is only used when we are printing declarators beyond + /// the first declarator within a declaration group. For example, given: + /// + /// \code + /// const int *x, *y; + /// \endcode + /// + /// SuppressSpecifiers will be false when printing the + /// declaration for "x", so that we will print "int *x"; it will be + /// \c true when we print "y", so that we suppress printing the + /// "const int" type specifier and instead only print the "*y". + bool SuppressSpecifiers : 1; + + /// \brief Whether type printing should skip printing the actual tag type. + /// + /// This is used when the caller needs to print a tag definition in front + /// of the type, as in constructs like the following: + /// + /// \code + /// typedef struct { int x, y; } Point; + /// \endcode + bool SuppressTag : 1; + + /// \brief Suppresses printing of scope specifiers. + bool SuppressScope : 1; + + /// \brief True when we are "dumping" rather than "pretty-printing", + /// where dumping involves printing the internal details of the AST + /// and pretty-printing involves printing something similar to + /// source code. + bool Dump : 1; + + /// \brief Whether we should print the sizes of constant array expressions + /// as written in the sources. + /// + /// This flag is determines whether arrays types declared as + /// + /// \code + /// int a[4+10*10]; + /// char a[] = "A string"; + /// \endcode + /// + /// will be printed as written or as follows: + /// + /// \code + /// int a[104]; + /// char a[9] = "A string"; + /// \endcode + bool ConstantArraySizeAsWritten : 1; + + /// \brief When printing an anonymous tag name, also print the location of + /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just + /// prints "<anonymous>" for the name. + bool AnonymousTagLocations : 1; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h new file mode 100644 index 0000000..2b3229e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h @@ -0,0 +1,251 @@ +//===--- RecordLayout.h - Layout information for a struct/union -*- 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 RecordLayout interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_LAYOUTINFO_H +#define LLVM_CLANG_AST_LAYOUTINFO_H + +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/DeclCXX.h" + +namespace clang { + class ASTContext; + class FieldDecl; + class RecordDecl; + class CXXRecordDecl; + +/// ASTRecordLayout - +/// This class contains layout information for one RecordDecl, +/// which is a struct/union/class. The decl represented must be a definition, +/// not a forward declaration. +/// This class is also used to contain layout information for one +/// ObjCInterfaceDecl. FIXME - Find appropriate name. +/// These objects are managed by ASTContext. +class ASTRecordLayout { + /// Size - Size of record in bits. + uint64_t Size; + + /// DataSize - Size of record in bits without tail padding. + uint64_t DataSize; + + /// FieldOffsets - Array of field offsets in bits. + uint64_t *FieldOffsets; + + // Alignment - Alignment of record in bits. + unsigned Alignment; + + // FieldCount - Number of fields. + unsigned FieldCount; + +public: + /// PrimaryBaseInfo - Contains info about a primary base. + struct PrimaryBaseInfo { + PrimaryBaseInfo() {} + + PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual) + : Value(Base, Base && IsVirtual) {} + + /// Value - Points to the primary base. The single-bit value + /// will be non-zero when the primary base is virtual. + llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value; + + /// getBase - Returns the primary base. + const CXXRecordDecl *getBase() const { return Value.getPointer(); } + + /// isVirtual - Returns whether the primary base is virtual or not. + bool isVirtual() const { return Value.getInt(); } + + friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) { + return X.Value == Y.Value; + } + }; + + /// primary_base_info_iterator - An iterator for iterating the primary base + /// class chain. + class primary_base_info_iterator { + /// Current - The current base class info. + PrimaryBaseInfo Current; + + public: + primary_base_info_iterator() {} + primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {} + + const PrimaryBaseInfo &operator*() const { return Current; } + + primary_base_info_iterator& operator++() { + const CXXRecordDecl *RD = Current.getBase(); + Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo(); + return *this; + } + + friend bool operator==(const primary_base_info_iterator &X, + const primary_base_info_iterator &Y) { + return X.Current == Y.Current; + } + friend bool operator!=(const primary_base_info_iterator &X, + const primary_base_info_iterator &Y) { + return !(X == Y); + } + }; + +private: + /// CXXRecordLayoutInfo - Contains C++ specific layout information. + struct CXXRecordLayoutInfo { + /// NonVirtualSize - The non-virtual size (in bits) of an object, which is + /// the size of the object without virtual bases. + uint64_t NonVirtualSize; + + /// NonVirtualAlign - The non-virtual alignment (in bits) of an object, + /// which is the alignment of the object without virtual bases. + uint64_t NonVirtualAlign; + + /// SizeOfLargestEmptySubobject - The size of the largest empty subobject + /// (either a base or a member). Will be zero if the class doesn't contain + /// any empty subobjects. + uint64_t SizeOfLargestEmptySubobject; + + /// PrimaryBase - The primary base info for this record. + PrimaryBaseInfo PrimaryBase; + + /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) + typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy; + + /// BaseOffsets - Contains a map from base classes to their offset. + BaseOffsetsMapTy BaseOffsets; + + /// VBaseOffsets - Contains a map from vbase classes to their offset. + BaseOffsetsMapTy VBaseOffsets; + }; + + /// CXXInfo - If the record layout is for a C++ record, this will have + /// C++ specific information about the record. + CXXRecordLayoutInfo *CXXInfo; + + friend class ASTContext; + + ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, + unsigned datasize, const uint64_t *fieldoffsets, + unsigned fieldcount); + + // Constructor for C++ records. + typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; + ASTRecordLayout(ASTContext &Ctx, + uint64_t size, unsigned alignment, uint64_t datasize, + const uint64_t *fieldoffsets, unsigned fieldcount, + uint64_t nonvirtualsize, unsigned nonvirtualalign, + uint64_t SizeOfLargestEmptySubobject, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseIsVirtual, + const BaseOffsetsMapTy& BaseOffsets, + const BaseOffsetsMapTy& VBaseOffsets); + + ~ASTRecordLayout() {} + + void Destroy(ASTContext &Ctx); + + ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT + void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT +public: + + /// getAlignment - Get the record alignment in bits. + unsigned getAlignment() const { return Alignment; } + + /// getSize - Get the record size in bits. + uint64_t getSize() const { return Size; } + + /// getFieldCount - Get the number of fields in the layout. + unsigned getFieldCount() const { return FieldCount; } + + /// getFieldOffset - Get the offset of the given field index, in + /// bits. + uint64_t getFieldOffset(unsigned FieldNo) const { + assert (FieldNo < FieldCount && "Invalid Field No"); + return FieldOffsets[FieldNo]; + } + + /// getDataSize() - Get the record data size, which is the record size + /// without tail padding, in bits. + uint64_t getDataSize() const { + return DataSize; + } + + /// getNonVirtualSize - Get the non-virtual size (in bits) of an object, + /// which is the size of the object without virtual bases. + uint64_t getNonVirtualSize() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->NonVirtualSize; + } + + /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object, + /// which is the alignment of the object without virtual bases. + unsigned getNonVirtualAlign() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->NonVirtualAlign; + } + + /// getPrimaryBaseInfo - Get the primary base info. + const PrimaryBaseInfo &getPrimaryBaseInfo() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->PrimaryBase; + } + + // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. + const CXXRecordDecl *getPrimaryBase() const { + return getPrimaryBaseInfo().getBase(); + } + + // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. + bool getPrimaryBaseWasVirtual() const { + return getPrimaryBaseInfo().isVirtual(); + } + + /// getBaseClassOffset - Get the offset, in bits, for the given base class. + uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); + + return CXXInfo->BaseOffsets[Base]; + } + + /// getVBaseClassOffset - Get the offset, in bits, for the given base class. + uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); + + return CXXInfo->VBaseOffsets[VBase]; + } + + uint64_t getSizeOfLargestEmptySubobject() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->SizeOfLargestEmptySubobject; + } + + primary_base_info_iterator primary_base_begin() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return primary_base_info_iterator(getPrimaryBaseInfo()); + } + + primary_base_info_iterator primary_base_end() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return primary_base_info_iterator(); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h new file mode 100644 index 0000000..07865e0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h @@ -0,0 +1,768 @@ +//===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- 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 RecursiveASTVisitor interface, which recursively +// traverses the entire AST. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS, Var) \ +return getDerived().Visit ## NAME(static_cast<CLASS*>(Var)) + +// We use preprocessor meta-programming to generate the Visit*() +// methods for all subclasses of Stmt, Decl, and Type. Some of the +// generated definitions, however, need to be customized. The +// meta-programming technique we use doesn't let us select which +// methods to generate. Therefore we have to generate ALL of them in +// a helper class RecursiveASTVisitorImpl, and override the ones we +// don't like in a child class RecursiveASTVisitor (C++ doesn't allow +// overriding a method in the same class). +// +// Do not use this class directly - use RecursiveASTVisitor instead. +template<typename Derived> +class RecursiveASTVisitorImpl { +public: + /// \brief Return a reference to the derived class. + Derived &getDerived() { return *static_cast<Derived*>(this); } + + /// \brief Recursively visit a statement or expression, by + /// dispatching to Visit*() based on the argument's dynamic type. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Stmt *S); + + /// \brief Recursively visit a type, by dispatching to + /// Visit*Type() based on the argument's getTypeClass() property. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is a Null type). + bool Visit(QualType T); + + /// \brief Recursively visit a declaration, by dispatching to + /// Visit*Decl() based on the argument's dynamic type. This is + /// NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Decl *D); + + /// \brief Recursively visit a C++ nested-name-specifier. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Recursively visit a template name. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateName(TemplateName Template); + + /// \brief Recursively visit a template argument. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArgument(const TemplateArgument &Arg); + + /// \brief Recursively visit a set of template arguments. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + + // If the implementation chooses not to implement a certain visit method, fall + // back on VisitExpr or whatever else is the superclass. +#define STMT(CLASS, PARENT) \ +bool Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT, S); } +#include "clang/AST/StmtNodes.inc" + + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. +#define BINOP_FALLBACK(NAME) \ +bool VisitBin ## NAME(BinaryOperator *S) { \ +DISPATCH(BinaryOperator, BinaryOperator, S); \ +} + BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) + BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) + BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) + BINOP_FALLBACK(Shr) + + BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) + BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) + BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) + BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) + + BINOP_FALLBACK(Assign) + BINOP_FALLBACK(Comma) +#undef BINOP_FALLBACK + + // If the implementation doesn't implement compound assignment operator + // methods, fall back on VisitCompoundAssignOperator. +#define CAO_FALLBACK(NAME) \ +bool VisitBin ## NAME(CompoundAssignOperator *S) { \ +DISPATCH(CompoundAssignOperator, CompoundAssignOperator, S); \ +} + CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) + CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) + CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) + CAO_FALLBACK(XorAssign) +#undef CAO_FALLBACK + + // If the implementation doesn't implement unary operator methods, fall back + // on VisitUnaryOperator. +#define UNARYOP_FALLBACK(NAME) \ +bool VisitUnary ## NAME(UnaryOperator *S) { \ +DISPATCH(UnaryOperator, UnaryOperator, S); \ +} + UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) + UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) + UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) + + UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) + UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) + UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) + UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) +#undef UNARYOP_FALLBACK + + /// \brief Basis for statement and expression visitation, which + /// visits all of the substatements and subexpressions. + /// + /// The relation between Visit(Stmt *S) and this method is that + /// the former dispatches to Visit*() based on S's dynamic type, + /// which forwards the call up the inheritance chain until + /// reaching VisitStmt(), which then calls Visit() on each + /// substatement/subexpression. + bool VisitStmt(Stmt *S); + + /// \brief Basis for type visitation, which by default does nothing. + /// + /// The relation between Visit(QualType T) and this method is + /// that the former dispatches to Visit*Type(), which forwards the + /// call up the inheritance chain until reaching VisitType(). + bool VisitType(Type *T); + +#define TYPE(Class, Base) \ + bool Visit##Class##Type(Class##Type *T); +#include "clang/AST/TypeNodes.def" + + /// \brief Basis for declaration and definition visitation, which + /// visits all of the subnodes. + /// + /// The relation between Visit(Decl *) and this method is that the + /// former dispatches to Visit*Decl(), which forwards the call up + /// the inheritance chain until reaching VisitDecl(). + bool VisitDecl(Decl *D); + +#define DECL(Class, Base) \ + bool Visit##Class##Decl(Class##Decl *D) { \ + return getDerived().Visit##Base(D); \ + } +#define ABSTRACT_DECL(Class, Base) DECL(Class, Base) +#include "clang/AST/DeclNodes.def" +}; + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Stmt *S) { + if (!S) + return false; + + // 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. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator, S); + case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator, S); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator, S); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator, S); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator, S); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator, S); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator, S); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator, S); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator, S); + + case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator, S); + case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator, S); + case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator, S); + case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator, S); + case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator, S); + case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator, S); + + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator, S); + case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator, S); + case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator, S); + case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator, S); + case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator, S); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator, S); + case BinaryOperator::MulAssign: + DISPATCH(BinMulAssign, CompoundAssignOperator, S); + case BinaryOperator::DivAssign: + DISPATCH(BinDivAssign, CompoundAssignOperator, S); + case BinaryOperator::RemAssign: + DISPATCH(BinRemAssign, CompoundAssignOperator, S); + case BinaryOperator::AddAssign: + DISPATCH(BinAddAssign, CompoundAssignOperator, S); + case BinaryOperator::SubAssign: + DISPATCH(BinSubAssign, CompoundAssignOperator, S); + case BinaryOperator::ShlAssign: + DISPATCH(BinShlAssign, CompoundAssignOperator, S); + case BinaryOperator::ShrAssign: + DISPATCH(BinShrAssign, CompoundAssignOperator, S); + case BinaryOperator::AndAssign: + DISPATCH(BinAndAssign, CompoundAssignOperator, S); + case BinaryOperator::OrAssign: + DISPATCH(BinOrAssign, CompoundAssignOperator, S); + case BinaryOperator::XorAssign: + DISPATCH(BinXorAssign, CompoundAssignOperator, S); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator, S); + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { + case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator, S); + case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator, S); + case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator, S); + case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator, S); + case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator, S); + case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator, S); + case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator, S); + case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator, S); + case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator, S); + case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator, S); + case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator, S); + case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator, S); + case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator, S); + case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator, S); + } + } + + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ +case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S); +#include "clang/AST/StmtNodes.inc" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(QualType T) { + if (T.isNull()) + return false; + + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + case Type::Class: DISPATCH(Class##Type, Class##Type, T.getTypePtr()); +#include "clang/AST/TypeNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Decl *D) { + if (!D) + return false; + + switch (D->getKind()) { +#define ABSTRACT_DECL(Class, Base) +#define DECL(Class, Base) \ + case Decl::Class: DISPATCH(Class##Decl, Class##Decl, D); +#include "clang/AST/DeclNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitNestedNameSpecifier( + NestedNameSpecifier *NNS) { + if (NNS->getPrefix() && + getDerived().VisitNestedNameSpecifier(NNS->getPrefix())) + return true; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::Global: + return false; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return Visit(QualType(NNS->getAsType(), 0)); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateName(TemplateName Template) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + return DTN->getQualifier() && + getDerived().VisitNestedNameSpecifier(DTN->getQualifier()); + + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + return getDerived().VisitNestedNameSpecifier(QTN->getQualifier()); + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArgument( + const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + return false; + + case TemplateArgument::Type: + return Visit(Arg.getAsType()); + + case TemplateArgument::Template: + return getDerived().VisitTemplateName(Arg.getAsTemplate()); + + case TemplateArgument::Expression: + return getDerived().Visit(Arg.getAsExpr()); + + case TemplateArgument::Pack: + return getDerived().VisitTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArguments( + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) + if (getDerived().VisitTemplateArgument(Args[I])) + return true; + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitStmt(Stmt *Node) { + for (Stmt::child_iterator C = Node->child_begin(), CEnd = Node->child_end(); + C != CEnd; ++C) { + if (Visit(*C)) + return true; + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitType(Type *T) { + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBuiltinType(BuiltinType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitComplexType(ComplexType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitPointerType(PointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBlockPointerType( + BlockPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitReferenceType(ReferenceType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitLValueReferenceType( + LValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRValueReferenceType( + RValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitMemberPointerType( + MemberPointerType *T) { + if (Visit(QualType(T->getClass(), 0)) || Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitArrayType(ArrayType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitConstantArrayType( + ConstantArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitIncompleteArrayType( + IncompleteArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVariableArrayType( + VariableArrayType *T) { + if (Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedArrayType( + DependentSizedArrayType *T) { + if (T->getSizeExpr() && Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedExtVectorType( + DependentSizedExtVectorType *T) { + if ((T->getSizeExpr() && Visit(T->getSizeExpr())) || + Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVectorType(VectorType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitExtVectorType(ExtVectorType *T) { + return getDerived().VisitVectorType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionType(FunctionType *T) { + if (Visit(T->getResultType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionNoProtoType( + FunctionNoProtoType *T) { + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionProtoType( + FunctionProtoType *T) { + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + if (Visit(*A)) + return true; + } + + for (FunctionProtoType::exception_iterator E = T->exception_begin(), + EEnd = T->exception_end(); + E != EEnd; ++E) { + if (Visit(*E)) + return true; + } + + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitUnresolvedUsingType( + UnresolvedUsingType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypedefType(TypedefType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfExprType(TypeOfExprType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfType(TypeOfType *T) { + if (Visit(T->getUnderlyingType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecltypeType(DecltypeType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTagType(TagType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRecordType(RecordType *T) { + return getDerived().VisitTagType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitEnumType(EnumType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateTypeParmType( + TemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitSubstTemplateTypeParmType( + SubstTemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateSpecializationType( + TemplateSpecializationType *T) { + if (getDerived().VisitTemplateName(T->getTemplateName()) || + getDerived().VisitTemplateArguments(T->getArgs(), T->getNumArgs())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitInjectedClassNameType( + InjectedClassNameType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitElaboratedType(ElaboratedType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + if (Visit(T->getNamedType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentNameType( + DependentNameType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + + if (T->getTemplateId() && + getDerived().VisitTemplateSpecializationType( + const_cast<TemplateSpecializationType *>(T->getTemplateId()))) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCInterfaceType( + ObjCInterfaceType *T) { + return getDerived().VisitObjCObjectType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectType(ObjCObjectType *T) { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + if (Visit(T->getBaseType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectPointerType( + ObjCObjectPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecl(Decl *D) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) { + for (DeclContext::decl_iterator Child = DC->decls_begin(), + ChildEnd = DC->decls_end(); + Child != ChildEnd; ++Child) + if (Visit(*Child)) + return true; + + return false; + } + + return false; +} + +/// \brief A visitor that recursively walks the entire Clang AST. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously +/// recurring template pattern) and override any of the Visit* +/// methods (except Visit()) for declaration, type, statement, +/// expression, or other AST nodes where the visitor should customize +/// behavior. Returning "true" from one of these overridden functions +/// will abort the entire traversal. An overridden Visit* method +/// will not descend further into the AST for that node unless +/// Base::Visit* is called. +template<typename Derived> +class RecursiveASTVisitor : public RecursiveASTVisitorImpl<Derived> { + typedef RecursiveASTVisitorImpl<Derived> Impl; +public: + typedef RecursiveASTVisitor<Derived> Base; + + bool VisitDeclaratorDecl(DeclaratorDecl *D); + bool VisitFunctionDecl(FunctionDecl *D); + bool VisitVarDecl(VarDecl *D); + bool VisitBlockDecl(BlockDecl *D); + bool VisitDeclStmt(DeclStmt *S); + bool VisitFunctionType(FunctionType *F); + bool VisitFunctionProtoType(FunctionProtoType *F); +}; + +#define DEFINE_VISIT(Type, Name, Statement) \ + template<typename Derived> \ + bool RecursiveASTVisitor<Derived>::Visit ## Type (Type *Name) { \ + if (Impl::Visit ## Type (Name)) return true; \ + { Statement; } \ + return false; \ + } + +DEFINE_VISIT(DeclaratorDecl, D, { + if (TypeSourceInfo *TInfo = D->getTypeSourceInfo()) + return this->Visit(TInfo->getType()); + }) + +DEFINE_VISIT(FunctionDecl, D, { + if (D->isThisDeclarationADefinition()) + return this->Visit(D->getBody()); + }) + +DEFINE_VISIT(VarDecl, D, return this->Visit(D->getInit())) + +DEFINE_VISIT(BlockDecl, D, return this->Visit(D->getBody())) + +DEFINE_VISIT(DeclStmt, S, { + for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + if (this->Visit(*I)) + return true; + } + }) + +// FunctionType is the common base class of FunctionNoProtoType (a +// K&R-style function declaration that has no information about +// its arguments) and FunctionProtoType. +DEFINE_VISIT(FunctionType, F, return this->Visit(F->getResultType())) + +DEFINE_VISIT(FunctionProtoType, F, { + for (unsigned i = 0; i != F->getNumArgs(); ++i) { + if (this->Visit(F->getArgType(i))) + return true; + } + for (unsigned i = 0; i != F->getNumExceptions(); ++i) { + if (this->Visit(F->getExceptionType(i))) + return true; + } + }) + +#undef DEFINE_VISIT + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h new file mode 100644 index 0000000..01f4b29 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h @@ -0,0 +1,179 @@ +//===-- Redeclarable.h - Base for Decls that can be redeclared -*- 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 Redeclarable interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_REDECLARABLE_H +#define LLVM_CLANG_AST_REDECLARABLE_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Casting.h" +#include <iterator> + +namespace clang { + +/// \brief Provides common interface for the Decls that can be redeclared. +template<typename decl_type> +class Redeclarable { + +protected: + // FIXME: PointerIntPair is a value class that should not be inherited from. + // This should change to using containment. + struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { + DeclLink(decl_type *D, bool isLatest) + : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } + + typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type; + + bool NextIsPrevious() const { return base_type::getInt() == false; } + bool NextIsLatest() const { return base_type::getInt() == true; } + decl_type *getNext() const { return base_type::getPointer(); } + }; + + struct PreviousDeclLink : public DeclLink { + PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } + }; + + struct LatestDeclLink : public DeclLink { + LatestDeclLink(decl_type *D) : DeclLink(D, true) { } + }; + + /// \brief Points to the next redeclaration in the chain. + /// + /// If NextIsPrevious() is true, this is a link to the previous declaration + /// of this same Decl. If NextIsLatest() is true, this is the first + /// declaration and Link points to the latest declaration. For example: + /// + /// #1 int f(int x, int y = 1); // <pointer to #3, true> + /// #2 int f(int x = 0, int y); // <pointer to #1, false> + /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false> + /// + /// If there is only one declaration, it is <pointer to self, true> + DeclLink RedeclLink; + +public: + Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { } + + /// \brief Return the previous declaration of this declaration or NULL if this + /// is the first declaration. + decl_type *getPreviousDeclaration() { + if (RedeclLink.NextIsPrevious()) + return RedeclLink.getNext(); + return 0; + } + const decl_type *getPreviousDeclaration() const { + return const_cast<decl_type *>( + static_cast<const decl_type*>(this))->getPreviousDeclaration(); + } + + /// \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(); + return D; + } + + /// \brief Return the first declaration of this declaration or itself if this + /// 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(); + return D; + } + + /// \brief Returns the most recent (re)declaration of this declaration. + decl_type *getMostRecentDeclaration() { + return getFirstDeclaration()->RedeclLink.getNext(); + } + + /// \brief Returns the most recent (re)declaration of this declaration. + const decl_type *getMostRecentDeclaration() const { + return getFirstDeclaration()->RedeclLink.getNext(); + } + + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the + /// first and only declaration. + void setPreviousDeclaration(decl_type *PrevDecl) { + 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())); + 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)); + } + + /// \brief Iterates through all the redeclarations of the same decl. + class redecl_iterator { + /// Current - The current declaration. + decl_type *Current; + decl_type *Starter; + + public: + typedef decl_type* value_type; + typedef decl_type* reference; + typedef decl_type* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + redecl_iterator() : Current(0) { } + explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { } + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + redecl_iterator& operator++() { + assert(Current && "Advancing while iterator has reached end"); + // Get either previous decl or latest decl. + decl_type *Next = Current->RedeclLink.getNext(); + Current = (Next != Starter ? Next : 0); + return *this; + } + + redecl_iterator operator++(int) { + redecl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(redecl_iterator x, redecl_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(redecl_iterator x, redecl_iterator y) { + return x.Current != y.Current; + } + }; + + /// \brief Returns iterator for all the redeclarations of the same decl. + /// It will iterate at least once (when this decl is the only one). + redecl_iterator redecls_begin() const { + return redecl_iterator(const_cast<decl_type*>( + static_cast<const decl_type*>(this))); + } + redecl_iterator redecls_end() const { return redecl_iterator(); } +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h new file mode 100644 index 0000000..9deae15 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h @@ -0,0 +1,1381 @@ +//===--- Stmt.h - Classes for representing statements -----------*- 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 Stmt interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMT_H +#define LLVM_CLANG_AST_STMT_H + +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/StmtIterator.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/FullExpr.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" +#include <string> +using llvm::dyn_cast_or_null; + +namespace llvm { + class FoldingSetNodeID; +} + +namespace clang { + class ASTContext; + class Expr; + class Decl; + class ParmVarDecl; + class QualType; + class IdentifierInfo; + class SourceManager; + 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; + + class ExprIterator { + Stmt** I; + public: + ExprIterator(Stmt** i) : I(i) {} + ExprIterator() : I(0) {} + ExprIterator& operator++() { ++I; return *this; } + ExprIterator operator-(size_t i) { return I-i; } + ExprIterator operator+(size_t i) { return I+i; } + Expr* operator[](size_t idx); + // FIXME: Verify that this will correctly return a signed distance. + signed operator-(const ExprIterator& R) const { return I - R.I; } + Expr* operator*() const; + Expr* operator->() const; + bool operator==(const ExprIterator& R) const { return I == R.I; } + bool operator!=(const ExprIterator& R) const { return I != R.I; } + bool operator>(const ExprIterator& R) const { return I > R.I; } + bool operator>=(const ExprIterator& R) const { return I >= R.I; } + }; + + class ConstExprIterator { + const Stmt * const *I; + public: + ConstExprIterator(const Stmt * const *i) : I(i) {} + ConstExprIterator() : I(0) {} + ConstExprIterator& operator++() { ++I; return *this; } + ConstExprIterator operator+(size_t i) const { return I+i; } + ConstExprIterator operator-(size_t i) const { return I-i; } + const Expr * operator[](size_t idx) const; + signed operator-(const ConstExprIterator& R) const { return I - R.I; } + const Expr * operator*() const; + const Expr * operator->() const; + bool operator==(const ConstExprIterator& R) const { return I == R.I; } + bool operator!=(const ConstExprIterator& R) const { return I != R.I; } + bool operator>(const ConstExprIterator& R) const { return I > R.I; } + bool operator>=(const ConstExprIterator& R) const { return I >= R.I; } + }; + +//===----------------------------------------------------------------------===// +// AST classes for statements. +//===----------------------------------------------------------------------===// + +/// Stmt - This represents one statement. +/// +class Stmt { +public: + enum StmtClass { + NoStmtClass = 0, +#define STMT(CLASS, PARENT) CLASS##Class, +#define STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class, +#define LAST_STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" +}; +private: + /// \brief The statement class. + const unsigned sClass : 8; + + /// \brief The reference count for this statement. + unsigned RefCount : 24; + + // Make vanilla 'new' and 'delete' illegal for Stmts. +protected: + void* operator new(size_t bytes) throw() { + assert(0 && "Stmts cannot be allocated with regular 'new'."); + return 0; + } + void operator delete(void* data) throw() { + assert(0 && "Stmts cannot be released with regular 'delete'."); + } + +public: + // Only allow allocation of Stmts using the allocator in ASTContext + // or by doing a placement new. + void* operator new(size_t bytes, ASTContext& C, + unsigned alignment = 8) throw() { + return ::operator new(bytes, C, alignment); + } + + void* operator new(size_t bytes, ASTContext* C, + unsigned alignment = 8) throw() { + return ::operator new(bytes, *C, alignment); + } + + void* operator new(size_t bytes, void* mem) throw() { + return mem; + } + + void operator delete(void*, ASTContext&, unsigned) throw() { } + void operator delete(void*, ASTContext*, unsigned) throw() { } + void operator delete(void*, std::size_t) throw() { } + void operator delete(void*, void*) throw() { } + +public: + /// \brief A placeholder type used to construct an empty shell of a + /// type, that will be filled in later (e.g., by some + /// de-serialization). + struct EmptyShell { }; + +protected: + /// DestroyChildren - Invoked by destructors of subclasses of Stmt to + /// recursively release child AST nodes. + void DestroyChildren(ASTContext& Ctx); + + /// \brief Construct an empty statement. + explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { + if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + } + + /// \brief Virtual method that performs the actual destruction of + /// this statement. + /// + /// Subclasses should override this method (not Destroy()) to + /// provide class-specific destruction. + virtual void DoDestroy(ASTContext &Ctx); + +public: + Stmt(StmtClass SC) : sClass(SC), RefCount(1) { + if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); + } + virtual ~Stmt() {} + +#ifndef NDEBUG + /// \brief True if this statement's refcount is in a valid state. + /// Should be used only in assertions. + bool isRetained() const { + return (RefCount >= 1); + } +#endif + + /// \brief Destroy the current statement and its children. + void Destroy(ASTContext &Ctx) { + assert(RefCount >= 1); + if (--RefCount == 0) + DoDestroy(Ctx); + } + + /// \brief Increases the reference count for this statement. + /// + /// Invoke the Retain() operation when this statement or expression + /// is being shared by another owner. + Stmt *Retain() { + assert(RefCount >= 1); + ++RefCount; + return this; + } + + StmtClass getStmtClass() const { + assert(RefCount >= 1 && "Referencing already-destroyed statement!"); + return (StmtClass)sClass; + } + const char *getStmtClassName() const; + + /// 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. + virtual SourceRange getSourceRange() const = 0; + SourceLocation getLocStart() const { return getSourceRange().getBegin(); } + SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + + // global temp stats (until we have a per-module visitor) + static void addStmtClass(const StmtClass s); + static bool CollectingStats(bool Enable = false); + 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; + + /// dumpAll - This does a dump of the specified AST fragment and all subtrees. + void dumpAll() const; + void dumpAll(SourceManager &SM) const; + + /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST + /// back to its original source language syntax. + void dumpPretty(ASTContext& Context) const; + void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper, + const PrintingPolicy &Policy, + unsigned Indentation = 0) const { + printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); + } + void printPretty(llvm::raw_ostream &OS, ASTContext &Context, + PrinterHelper *Helper, + const PrintingPolicy &Policy, + unsigned Indentation = 0) const; + + /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only + /// works on systems with GraphViz (Mac OS X) or dot+gv installed. + void viewAST() const; + + // Implement isa<T> support. + static bool classof(const Stmt *) { return true; } + + /// hasImplicitControlFlow - Some statements (e.g. short circuited operations) + /// contain implicit control-flow in the order their subexpressions + /// are evaluated. This predicate returns true if this statement has + /// such implicit control-flow. Such statements are also specially handled + /// within CFGs. + bool hasImplicitControlFlow() const; + + /// Child Iterators: All subclasses must implement child_begin and child_end + /// to permit easy iteration over the substatements/subexpessions of an + /// AST node. This permits easy iteration over all nodes in the AST. + typedef StmtIterator child_iterator; + typedef ConstStmtIterator const_child_iterator; + + virtual child_iterator child_begin() = 0; + virtual child_iterator child_end() = 0; + + const_child_iterator child_begin() const { + return const_child_iterator(const_cast<Stmt*>(this)->child_begin()); + } + + const_child_iterator child_end() const { + return const_child_iterator(const_cast<Stmt*>(this)->child_end()); + } + + /// \brief Produce a unique representation of the given statement. + /// + /// \brief ID once the profiling operation is complete, will contain + /// the unique representation of the given statement. + /// + /// \brief Context the AST context in which the statement resides + /// + /// \brief Canonical whether the profile should be based on the canonical + /// representation of this statement (e.g., where non-type template + /// parameters are identified by index/level rather than their + /// declaration pointers) or the exact representation of the statement as + /// written in the source. + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + bool Canonical); +}; + +/// DeclStmt - Adaptor class for mixing declarations with statements and +/// expressions. For example, CompoundStmt mixes statements, expressions +/// and declarations (variables, types). Another example is ForStmt, where +/// the first statement can be an expression or a declaration. +/// +class DeclStmt : public Stmt { + DeclGroupRef DG; + SourceLocation StartLoc, EndLoc; + +protected: + virtual void DoDestroy(ASTContext &Ctx); + +public: + DeclStmt(DeclGroupRef dg, SourceLocation startLoc, + SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), + StartLoc(startLoc), EndLoc(endLoc) {} + + /// \brief Build an empty declaration statement. + explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } + + /// isSingleDecl - This method returns true if this DeclStmt refers + /// to a single Decl. + bool isSingleDecl() const { + return DG.isSingleDecl(); + } + + const Decl *getSingleDecl() const { return DG.getSingleDecl(); } + Decl *getSingleDecl() { return DG.getSingleDecl(); } + + const DeclGroupRef getDeclGroup() const { return DG; } + DeclGroupRef getDeclGroup() { return DG; } + void setDeclGroup(DeclGroupRef DGR) { DG = DGR; } + + SourceLocation getStartLoc() const { return StartLoc; } + void setStartLoc(SourceLocation L) { StartLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(StartLoc, EndLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclStmtClass; + } + static bool classof(const DeclStmt *) { return true; } + + // Iterators over subexpressions. + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + typedef DeclGroupRef::iterator decl_iterator; + typedef DeclGroupRef::const_iterator const_decl_iterator; + + decl_iterator decl_begin() { return DG.begin(); } + decl_iterator decl_end() { return DG.end(); } + const_decl_iterator decl_begin() const { return DG.begin(); } + const_decl_iterator decl_end() const { return DG.end(); } +}; + +/// NullStmt - This is the null statement ";": C99 6.8.3p3. +/// +class NullStmt : public Stmt { + SourceLocation SemiLoc; +public: + NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {} + + /// \brief Build an empty null statement. + explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { } + + SourceLocation getSemiLoc() const { return SemiLoc; } + void setSemiLoc(SourceLocation L) { SemiLoc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == NullStmtClass; + } + static bool classof(const NullStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CompoundStmt - This represents a group of statements like { stmt stmt }. +/// +class CompoundStmt : public Stmt { + Stmt** Body; + unsigned NumStmts; + SourceLocation LBracLoc, RBracLoc; +public: + CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts, + SourceLocation LB, SourceLocation RB) + : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) { + if (NumStmts == 0) { + Body = 0; + return; + } + + Body = new (C) Stmt*[NumStmts]; + memcpy(Body, StmtStart, numStmts * sizeof(*Body)); + } + + // \brief Build an empty compound statement. + explicit CompoundStmt(EmptyShell Empty) + : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { } + + void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts); + + bool body_empty() const { return NumStmts == 0; } + unsigned size() const { return NumStmts; } + + typedef Stmt** body_iterator; + body_iterator body_begin() { return Body; } + body_iterator body_end() { return Body + NumStmts; } + Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; } + + typedef Stmt* const * const_body_iterator; + const_body_iterator body_begin() const { return Body; } + const_body_iterator body_end() const { return Body + NumStmts; } + const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; } + + typedef std::reverse_iterator<body_iterator> reverse_body_iterator; + reverse_body_iterator body_rbegin() { + return reverse_body_iterator(body_end()); + } + reverse_body_iterator body_rend() { + return reverse_body_iterator(body_begin()); + } + + typedef std::reverse_iterator<const_body_iterator> + const_reverse_body_iterator; + + const_reverse_body_iterator body_rbegin() const { + return const_reverse_body_iterator(body_end()); + } + + const_reverse_body_iterator body_rend() const { + return const_reverse_body_iterator(body_begin()); + } + + virtual SourceRange getSourceRange() const { + return SourceRange(LBracLoc, RBracLoc); + } + + SourceLocation getLBracLoc() const { return LBracLoc; } + void setLBracLoc(SourceLocation L) { LBracLoc = L; } + SourceLocation getRBracLoc() const { return RBracLoc; } + void setRBracLoc(SourceLocation L) { RBracLoc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CompoundStmtClass; + } + static bool classof(const CompoundStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +// SwitchCase is the base class for CaseStmt and DefaultStmt, +class SwitchCase : public Stmt { +protected: + // A pointer to the following CaseStmt or DefaultStmt class, + // used by SwitchStmt. + SwitchCase *NextSwitchCase; + + SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} + +public: + const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } + + SwitchCase *getNextSwitchCase() { return NextSwitchCase; } + + void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } + + Stmt *getSubStmt() { return v_getSubStmt(); } + + virtual SourceRange getSourceRange() const { return SourceRange(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CaseStmtClass || + T->getStmtClass() == DefaultStmtClass; + } + static bool classof(const SwitchCase *) { return true; } +protected: + virtual Stmt* v_getSubStmt() = 0; +}; + +class CaseStmt : public SwitchCase { + enum { SUBSTMT, LHS, RHS, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for + // GNU "case 1 ... 4" extension + SourceLocation CaseLoc; + SourceLocation EllipsisLoc; + SourceLocation ColonLoc; + + virtual Stmt* v_getSubStmt() { return getSubStmt(); } +public: + CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, + SourceLocation ellipsisLoc, SourceLocation colonLoc) + : SwitchCase(CaseStmtClass) { + SubExprs[SUBSTMT] = 0; + SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); + SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); + CaseLoc = caseLoc; + EllipsisLoc = ellipsisLoc; + ColonLoc = colonLoc; + } + + /// \brief Build an empty switch case statement. + explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { } + + SourceLocation getCaseLoc() const { return CaseLoc; } + void setCaseLoc(SourceLocation L) { CaseLoc = L; } + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); } + Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); } + Stmt *getSubStmt() { return SubExprs[SUBSTMT]; } + + const Expr *getLHS() const { + return reinterpret_cast<const Expr*>(SubExprs[LHS]); + } + const Expr *getRHS() const { + return reinterpret_cast<const Expr*>(SubExprs[RHS]); + } + const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } + + void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } + void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); } + void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } + + + virtual SourceRange getSourceRange() const { + // Handle deeply nested case statements with iteration instead of recursion. + const CaseStmt *CS = this; + while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) + CS = CS2; + + return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CaseStmtClass; + } + static bool classof(const CaseStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class DefaultStmt : public SwitchCase { + Stmt* SubStmt; + SourceLocation DefaultLoc; + SourceLocation ColonLoc; + virtual Stmt* v_getSubStmt() { return getSubStmt(); } +public: + DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : + SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL), + ColonLoc(CL) {} + + /// \brief Build an empty default statement. + explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { } + + Stmt *getSubStmt() { return SubStmt; } + const Stmt *getSubStmt() const { return SubStmt; } + void setSubStmt(Stmt *S) { SubStmt = S; } + + SourceLocation getDefaultLoc() const { return DefaultLoc; } + void setDefaultLoc(SourceLocation L) { DefaultLoc = L; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(DefaultLoc, SubStmt->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == DefaultStmtClass; + } + static bool classof(const DefaultStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +class LabelStmt : public Stmt { + IdentifierInfo *Label; + Stmt *SubStmt; + SourceLocation IdentLoc; +public: + LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) + : Stmt(LabelStmtClass), Label(label), + SubStmt(substmt), IdentLoc(IL) {} + + // \brief Build an empty label statement. + explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } + + SourceLocation getIdentLoc() const { return IdentLoc; } + IdentifierInfo *getID() const { return Label; } + void setID(IdentifierInfo *II) { Label = II; } + const char *getName() const; + Stmt *getSubStmt() { return SubStmt; } + const Stmt *getSubStmt() const { return SubStmt; } + void setIdentLoc(SourceLocation L) { IdentLoc = L; } + void setSubStmt(Stmt *SS) { SubStmt = SS; } + + virtual SourceRange getSourceRange() const { + return SourceRange(IdentLoc, SubStmt->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == LabelStmtClass; + } + static bool classof(const LabelStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// IfStmt - This represents an if/then/else. +/// +class IfStmt : public Stmt { + enum { COND, THEN, ELSE, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + + /// \brief If non-NULL, the declaration in the "if" statement. + VarDecl *Var; + + SourceLocation IfLoc; + SourceLocation ElseLoc; + +public: + IfStmt(SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, + SourceLocation EL = SourceLocation(), Stmt *elsev = 0) + : Stmt(IfStmtClass), Var(var), IfLoc(IL), ElseLoc(EL) { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[THEN] = then; + SubExprs[ELSE] = elsev; + } + + /// \brief Build an empty if/then/else statement + explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } + + /// \brief Retrieve the variable declared in this "if" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// if (int x = foo()) { + /// printf("x is %d", x); + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + + 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]; } + void setThen(Stmt *S) { SubExprs[THEN] = S; } + const Stmt *getElse() const { return SubExprs[ELSE]; } + void setElse(Stmt *S) { SubExprs[ELSE] = S; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + Stmt *getThen() { return SubExprs[THEN]; } + Stmt *getElse() { return SubExprs[ELSE]; } + + SourceLocation getIfLoc() const { return IfLoc; } + void setIfLoc(SourceLocation L) { IfLoc = L; } + SourceLocation getElseLoc() const { return ElseLoc; } + void setElseLoc(SourceLocation L) { ElseLoc = L; } + + virtual SourceRange getSourceRange() const { + if (SubExprs[ELSE]) + return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); + else + return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == IfStmtClass; + } + static bool classof(const IfStmt *) { return true; } + + // Iterators over subexpressions. The iterators will include iterating + // over the initialization expression referenced by the condition variable. + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); +}; + +/// SwitchStmt - This represents a 'switch' stmt. +/// +class SwitchStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + VarDecl *Var; + // This points to a linked list of case and default statements. + SwitchCase *FirstCase; + SourceLocation SwitchLoc; + +protected: + virtual void DoDestroy(ASTContext &Ctx); + +public: + SwitchStmt(VarDecl *Var, Expr *cond) + : Stmt(SwitchStmtClass), Var(Var), FirstCase(0) + { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = NULL; + } + + /// \brief Build a empty switch statement. + explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } + + /// \brief Retrieve the variable declared in this "switch" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// switch (int x = foo()) { + /// case 0: break; + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + const Stmt *getBody() const { return SubExprs[BODY]; } + const SwitchCase *getSwitchCaseList() const { return FirstCase; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);} + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } + Stmt *getBody() { return SubExprs[BODY]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + SwitchCase *getSwitchCaseList() { return FirstCase; } + + /// \brief Set the case list for this switch statement. + /// + /// The caller is responsible for incrementing the retain counts on + /// all of the SwitchCase statements in this list. + void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } + + SourceLocation getSwitchLoc() const { return SwitchLoc; } + void setSwitchLoc(SourceLocation L) { SwitchLoc = L; } + + void setBody(Stmt *S, SourceLocation SL) { + SubExprs[BODY] = S; + SwitchLoc = SL; + } + void addSwitchCase(SwitchCase *SC) { + assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); + SC->Retain(); + SC->setNextSwitchCase(FirstCase); + FirstCase = SC; + } + virtual SourceRange getSourceRange() const { + return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == SwitchStmtClass; + } + static bool classof(const SwitchStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// WhileStmt - This represents a 'while' stmt. +/// +class WhileStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + VarDecl *Var; + Stmt* SubExprs[END_EXPR]; + SourceLocation WhileLoc; +public: + WhileStmt(VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) + : Stmt(WhileStmtClass), Var(Var) + { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + WhileLoc = WL; + } + + /// \brief Build an empty while statement. + explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } + + /// \brief Retrieve the variable declared in this "while" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// while (int x = random()) { + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + Stmt *getBody() { return SubExprs[BODY]; } + const Stmt *getBody() const { return SubExprs[BODY]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getWhileLoc() const { return WhileLoc; } + void setWhileLoc(SourceLocation L) { WhileLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == WhileStmtClass; + } + static bool classof(const WhileStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); +}; + +/// DoStmt - This represents a 'do/while' stmt. +/// +class DoStmt : public Stmt { + enum { COND, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + SourceLocation DoLoc; + SourceLocation WhileLoc; + SourceLocation RParenLoc; // Location of final ')' in do stmt condition. + +public: + DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL, + SourceLocation RP) + : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + } + + /// \brief Build an empty do-while statement. + explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + Stmt *getBody() { return SubExprs[BODY]; } + const Stmt *getBody() const { return SubExprs[BODY]; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getDoLoc() const { return DoLoc; } + void setDoLoc(SourceLocation L) { DoLoc = L; } + SourceLocation getWhileLoc() const { return WhileLoc; } + void setWhileLoc(SourceLocation L) { WhileLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(DoLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == DoStmtClass; + } + static bool classof(const DoStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of +/// the init/cond/inc parts of the ForStmt will be null if they were not +/// specified in the source. +/// +class ForStmt : public Stmt { + enum { INIT, COND, INC, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. + VarDecl *CondVar; + SourceLocation ForLoc; + SourceLocation LParenLoc, RParenLoc; + +public: + ForStmt(Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, + SourceLocation FL, SourceLocation LP, SourceLocation RP) + : Stmt(ForStmtClass), CondVar(condVar), ForLoc(FL), LParenLoc(LP), + RParenLoc(RP) + { + SubExprs[INIT] = Init; + SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); + SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); + SubExprs[BODY] = Body; + } + + /// \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. + /// \code + /// for (int x = random(); int y = mangle(x); ++x) { + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return CondVar; } + void setConditionVariable(VarDecl *V) { CondVar = V; } + + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } + Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } + Stmt *getBody() { return SubExprs[BODY]; } + + const Stmt *getInit() const { return SubExprs[INIT]; } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} + const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setInit(Stmt *S) { SubExprs[INIT] = S; } + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation L) { ForLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ForStmtClass; + } + static bool classof(const ForStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); +}; + +/// GotoStmt - This represents a direct goto. +/// +class GotoStmt : public Stmt { + LabelStmt *Label; + SourceLocation GotoLoc; + SourceLocation LabelLoc; +public: + GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) + : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} + + /// \brief Build an empty goto statement. + explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { } + + LabelStmt *getLabel() const { return Label; } + void setLabel(LabelStmt *S) { Label = S; } + + SourceLocation getGotoLoc() const { return GotoLoc; } + void setGotoLoc(SourceLocation L) { GotoLoc = L; } + SourceLocation getLabelLoc() const { return LabelLoc; } + void setLabelLoc(SourceLocation L) { LabelLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(GotoLoc, LabelLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GotoStmtClass; + } + static bool classof(const GotoStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// IndirectGotoStmt - This represents an indirect goto. +/// +class IndirectGotoStmt : public Stmt { + SourceLocation GotoLoc; + SourceLocation StarLoc; + Stmt *Target; +public: + IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, + Expr *target) + : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc), + Target((Stmt*)target) {} + + /// \brief Build an empty indirect goto statement. + explicit IndirectGotoStmt(EmptyShell Empty) + : Stmt(IndirectGotoStmtClass, Empty) { } + + void setGotoLoc(SourceLocation L) { GotoLoc = L; } + SourceLocation getGotoLoc() const { return GotoLoc; } + void setStarLoc(SourceLocation L) { StarLoc = L; } + SourceLocation getStarLoc() const { return StarLoc; } + + Expr *getTarget(); + const Expr *getTarget() const; + void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); } + + virtual SourceRange getSourceRange() const { + return SourceRange(GotoLoc, Target->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == IndirectGotoStmtClass; + } + static bool classof(const IndirectGotoStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// ContinueStmt - This represents a continue. +/// +class ContinueStmt : public Stmt { + SourceLocation ContinueLoc; +public: + ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} + + /// \brief Build an empty continue statement. + explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } + + SourceLocation getContinueLoc() const { return ContinueLoc; } + void setContinueLoc(SourceLocation L) { ContinueLoc = L; } + + virtual SourceRange getSourceRange() const { + return SourceRange(ContinueLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ContinueStmtClass; + } + static bool classof(const ContinueStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// BreakStmt - This represents a break. +/// +class BreakStmt : public Stmt { + SourceLocation BreakLoc; +public: + BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {} + + /// \brief Build an empty break statement. + explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } + + SourceLocation getBreakLoc() const { return BreakLoc; } + void setBreakLoc(SourceLocation L) { BreakLoc = L; } + + virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == BreakStmtClass; + } + static bool classof(const BreakStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +/// ReturnStmt - This represents a return, optionally of an expression: +/// return; +/// return 4; +/// +/// Note that GCC allows return with no argument in a function declared to +/// return a value, and it allows returning a value in functions declared to +/// return void. We explicitly model this in the AST, which means you can't +/// depend on the return type of the function and the presence of an argument. +/// +class ReturnStmt : public Stmt { + Stmt *RetExpr; + SourceLocation RetLoc; + const VarDecl *NRVOCandidate; + +public: + ReturnStmt(SourceLocation RL) + : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { } + + ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) + : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL), + NRVOCandidate(NRVOCandidate) {} + + /// \brief Build an empty return expression. + explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } + + const Expr *getRetValue() const; + Expr *getRetValue(); + void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); } + + SourceLocation getReturnLoc() const { return RetLoc; } + void setReturnLoc(SourceLocation L) { RetLoc = L; } + + /// \brief Retrieve the variable that might be used for the named return + /// value optimization. + /// + /// The optimization itself can only be performed if the variable is + /// also marked as an NRVO object. + const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } + void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ReturnStmtClass; + } + static bool classof(const ReturnStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// AsmStmt - This represents a GNU inline-assembly statement extension. +/// +class AsmStmt : public Stmt { + SourceLocation AsmLoc, RParenLoc; + StringLiteral *AsmStr; + + bool IsSimple; + bool IsVolatile; + bool MSAsm; + + unsigned NumOutputs; + unsigned NumInputs; + unsigned NumClobbers; + + // FIXME: If we wanted to, we could allocate all of these in one big array. + IdentifierInfo **Names; + StringLiteral **Constraints; + Stmt **Exprs; + StringLiteral **Clobbers; + +protected: + virtual void DoDestroy(ASTContext &Ctx); + +public: + 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), + Names(0), Constraints(0), Exprs(0), Clobbers(0) { } + + SourceLocation getAsmLoc() const { return AsmLoc; } + void setAsmLoc(SourceLocation L) { AsmLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + bool isVolatile() const { return IsVolatile; } + void setVolatile(bool V) { IsVolatile = V; } + bool isSimple() const { return IsSimple; } + void setSimple(bool V) { IsSimple = V; } + bool isMSAsm() const { return MSAsm; } + void setMSAsm(bool V) { MSAsm = V; } + + //===--- Asm String Analysis ---===// + + const StringLiteral *getAsmString() const { return AsmStr; } + StringLiteral *getAsmString() { return AsmStr; } + void setAsmString(StringLiteral *E) { AsmStr = E; } + + /// AsmStringPiece - this is part of a decomposed asm string specification + /// (for use with the AnalyzeAsmString function below). An asm string is + /// considered to be a concatenation of these parts. + class AsmStringPiece { + public: + enum Kind { + String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". + Operand // Operand reference, with optional modifier %c4. + }; + private: + Kind MyKind; + std::string Str; + unsigned OperandNo; + public: + AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} + AsmStringPiece(unsigned OpNo, char Modifier) + : MyKind(Operand), Str(), OperandNo(OpNo) { + Str += Modifier; + } + + bool isString() const { return MyKind == String; } + bool isOperand() const { return MyKind == Operand; } + + const std::string &getString() const { + assert(isString()); + return Str; + } + + unsigned getOperandNo() const { + assert(isOperand()); + return OperandNo; + } + + /// getModifier - Get the modifier for this operand, if present. This + /// returns '\0' if there was no modifier. + char getModifier() const { + assert(isOperand()); + return Str[0]; + } + }; + + /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing + /// it into pieces. If the asm string is erroneous, emit errors and return + /// true, otherwise return false. This handles canonicalization and + /// translation of strings from GCC syntax to LLVM IR syntax, and handles + //// flattening of named references like %[foo] to Operand AsmStringPiece's. + unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces, + ASTContext &C, unsigned &DiagOffs) const; + + + //===--- Output operands ---===// + + unsigned getNumOutputs() const { return NumOutputs; } + + IdentifierInfo *getOutputIdentifier(unsigned i) const { + return Names[i]; + } + + llvm::StringRef getOutputName(unsigned i) const { + if (IdentifierInfo *II = getOutputIdentifier(i)) + return II->getName(); + + return llvm::StringRef(); + } + + /// getOutputConstraint - Return the constraint string for the specified + /// output operand. All output constraints are known to be non-empty (either + /// '=' or '+'). + llvm::StringRef getOutputConstraint(unsigned i) const; + + const StringLiteral *getOutputConstraintLiteral(unsigned i) const { + return Constraints[i]; + } + StringLiteral *getOutputConstraintLiteral(unsigned i) { + return Constraints[i]; + } + + Expr *getOutputExpr(unsigned i); + + const Expr *getOutputExpr(unsigned i) const { + return const_cast<AsmStmt*>(this)->getOutputExpr(i); + } + + /// isOutputPlusConstraint - Return true if the specified output constraint + /// is a "+" constraint (which is both an input and an output) or false if it + /// is an "=" constraint (just an output). + bool isOutputPlusConstraint(unsigned i) const { + return getOutputConstraint(i)[0] == '+'; + } + + /// getNumPlusOperands - Return the number of output operands that have a "+" + /// constraint. + unsigned getNumPlusOperands() const; + + //===--- Input operands ---===// + + unsigned getNumInputs() const { return NumInputs; } + + IdentifierInfo *getInputIdentifier(unsigned i) const { + return Names[i + NumOutputs]; + } + + llvm::StringRef getInputName(unsigned i) const { + if (IdentifierInfo *II = getInputIdentifier(i)) + return II->getName(); + + return llvm::StringRef(); + } + + /// getInputConstraint - Return the specified input constraint. Unlike output + /// constraints, these can be empty. + llvm::StringRef getInputConstraint(unsigned i) const; + + const StringLiteral *getInputConstraintLiteral(unsigned i) const { + return Constraints[i + NumOutputs]; + } + StringLiteral *getInputConstraintLiteral(unsigned i) { + return Constraints[i + NumOutputs]; + } + + Expr *getInputExpr(unsigned i); + + const Expr *getInputExpr(unsigned i) const { + return const_cast<AsmStmt*>(this)->getInputExpr(i); + } + + void setOutputsAndInputsAndClobbers(ASTContext &C, + IdentifierInfo **Names, + StringLiteral **Constraints, + Stmt **Exprs, + unsigned NumOutputs, + unsigned NumInputs, + StringLiteral **Clobbers, + unsigned NumClobbers); + + //===--- Other ---===// + + /// getNamedOperand - Given a symbolic operand reference like %[foo], + /// translate this into a numeric value needed to reference the same operand. + /// This returns -1 if the operand name is invalid. + int getNamedOperand(llvm::StringRef SymbolicName) const; + + unsigned getNumClobbers() const { return NumClobbers; } + StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } + const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AsmLoc, RParenLoc); + } + + static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;} + static bool classof(const AsmStmt *) { return true; } + + // Input expr iterators. + + typedef ExprIterator inputs_iterator; + typedef ConstExprIterator const_inputs_iterator; + + inputs_iterator begin_inputs() { + return &Exprs[0] + NumOutputs; + } + + inputs_iterator end_inputs() { + return &Exprs[0] + NumOutputs + NumInputs; + } + + const_inputs_iterator begin_inputs() const { + return &Exprs[0] + NumOutputs; + } + + const_inputs_iterator end_inputs() const { + return &Exprs[0] + NumOutputs + NumInputs; + } + + // Output expr iterators. + + typedef ExprIterator outputs_iterator; + typedef ConstExprIterator const_outputs_iterator; + + outputs_iterator begin_outputs() { + return &Exprs[0]; + } + outputs_iterator end_outputs() { + return &Exprs[0] + NumOutputs; + } + + const_outputs_iterator begin_outputs() const { + return &Exprs[0]; + } + const_outputs_iterator end_outputs() const { + return &Exprs[0] + NumOutputs; + } + + // Child iterators + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h new file mode 100644 index 0000000..4e87c27 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h @@ -0,0 +1,113 @@ +//===--- StmtCXX.h - Classes for representing C++ statements ----*- 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 C++ statement AST node classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTCXX_H +#define LLVM_CLANG_AST_STMTCXX_H + +#include "clang/AST/Stmt.h" + +namespace clang { + +class VarDecl; + +/// CXXCatchStmt - This represents a C++ catch block. +/// +class CXXCatchStmt : public Stmt { + SourceLocation CatchLoc; + /// The exception-declaration of the type. + VarDecl *ExceptionDecl; + /// The handler block. + Stmt *HandlerBlock; + +protected: + virtual void DoDestroy(ASTContext& Ctx); + +public: + CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) + : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), + HandlerBlock(handlerBlock) {} + + virtual SourceRange getSourceRange() const { + return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); + } + + SourceLocation getCatchLoc() const { return CatchLoc; } + VarDecl *getExceptionDecl() const { return ExceptionDecl; } + QualType getCaughtType() const; + Stmt *getHandlerBlock() const { return HandlerBlock; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXCatchStmtClass; + } + static bool classof(const CXXCatchStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// CXXTryStmt - A C++ try block, including all handlers. +/// +class CXXTryStmt : public Stmt { + SourceLocation TryLoc; + unsigned NumHandlers; + + CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, + unsigned numHandlers); + +public: + static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, + Stmt *tryBlock, Stmt **handlers, + unsigned numHandlers); + + virtual SourceRange getSourceRange() const { + return SourceRange(getTryLoc(), getEndLoc()); + } + + SourceLocation getTryLoc() const { return TryLoc; } + SourceLocation getEndLoc() const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); + return Stmts[NumHandlers]->getLocEnd(); + } + + CompoundStmt *getTryBlock() { + Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); + return llvm::cast<CompoundStmt>(Stmts[0]); + } + const CompoundStmt *getTryBlock() const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); + return llvm::cast<CompoundStmt>(Stmts[0]); + } + + unsigned getNumHandlers() const { return NumHandlers; } + CXXCatchStmt *getHandler(unsigned i) { + Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); + return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + } + const CXXCatchStmt *getHandler(unsigned i) const { + Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); + return llvm::cast<CXXCatchStmt>(Stmts[i + 1]); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTryStmtClass; + } + static bool classof(const CXXTryStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h new file mode 100644 index 0000000..25d0152 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h @@ -0,0 +1,83 @@ +//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- 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 template specialization of llvm::GraphTraits to +// treat ASTs (Stmt*) as graphs +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H +#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H + +#include "clang/AST/Stmt.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DepthFirstIterator.h" + +namespace llvm { + +//template <typename T> struct GraphTraits; + + +template <> struct GraphTraits<clang::Stmt*> { + typedef clang::Stmt NodeType; + typedef clang::Stmt::child_iterator ChildIteratorType; + typedef llvm::df_iterator<clang::Stmt*> nodes_iterator; + + static NodeType* getEntryNode(clang::Stmt* S) { return S; } + + static inline ChildIteratorType child_begin(NodeType* N) { + if (N) return N->child_begin(); + else return ChildIteratorType(); + } + + static inline ChildIteratorType child_end(NodeType* N) { + if (N) return N->child_end(); + else return ChildIteratorType(); + } + + static nodes_iterator nodes_begin(clang::Stmt* S) { + return df_begin(S); + } + + static nodes_iterator nodes_end(clang::Stmt* S) { + return df_end(S); + } +}; + + +template <> struct GraphTraits<const clang::Stmt*> { + typedef const clang::Stmt NodeType; + typedef clang::Stmt::const_child_iterator ChildIteratorType; + typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator; + + static NodeType* getEntryNode(const clang::Stmt* S) { return S; } + + static inline ChildIteratorType child_begin(NodeType* N) { + if (N) return N->child_begin(); + else return ChildIteratorType(); + } + + static inline ChildIteratorType child_end(NodeType* N) { + if (N) return N->child_end(); + else return ChildIteratorType(); + } + + static nodes_iterator nodes_begin(const clang::Stmt* S) { + return df_begin(S); + } + + static nodes_iterator nodes_end(const clang::Stmt* S) { + return df_end(S); + } +}; + + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h new file mode 100644 index 0000000..a48f4e6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h @@ -0,0 +1,150 @@ +//===--- StmtIterator.h - Iterators for Statements ------------------------===// +// +// 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 StmtIterator and ConstStmtIterator classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMT_ITR_H +#define LLVM_CLANG_AST_STMT_ITR_H + +#include "llvm/System/DataTypes.h" +#include <cassert> +#include <iterator> + +namespace clang { + +class Stmt; +class Decl; +class VariableArrayType; + +class StmtIteratorBase { +protected: + enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3, + Flags = 0x3 }; + + Stmt **stmt; + union { Decl *decl; Decl **DGI; }; + uintptr_t RawVAPtr; + Decl **DGE; + + bool inDecl() const { + return (RawVAPtr & Flags) == DeclMode; + } + + bool inDeclGroup() const { + return (RawVAPtr & Flags) == DeclGroupMode; + } + + bool inSizeOfTypeVA() const { + return (RawVAPtr & Flags) == SizeOfTypeVAMode; + } + + bool inStmt() const { + return (RawVAPtr & Flags) == 0; + } + + VariableArrayType* getVAPtr() const { + return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags); + } + + void setVAPtr(VariableArrayType* P) { + assert (inDecl() || inDeclGroup() || inSizeOfTypeVA()); + RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags); + } + + void NextDecl(bool ImmediateAdvance = true); + bool HandleDecl(Decl* D); + void NextVA(); + + Stmt*& GetDeclExpr() const; + + StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {} + StmtIteratorBase(Decl *d, Stmt **s); + StmtIteratorBase(VariableArrayType *t); + StmtIteratorBase(Decl **dgi, Decl **dge); + StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {} +}; + + +template <typename DERIVED, typename REFERENCE> +class StmtIteratorImpl : public StmtIteratorBase, + public std::iterator<std::forward_iterator_tag, + REFERENCE, ptrdiff_t, + REFERENCE, REFERENCE> { +protected: + StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} +public: + StmtIteratorImpl() {} + StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} + StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} + StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {} + StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {} + + DERIVED& operator++() { + if (inDecl() || inDeclGroup()) { + if (getVAPtr()) NextVA(); + else NextDecl(); + } + else if (inSizeOfTypeVA()) + NextVA(); + else + ++stmt; + + return static_cast<DERIVED&>(*this); + } + + DERIVED operator++(int) { + DERIVED tmp = static_cast<DERIVED&>(*this); + operator++(); + return tmp; + } + + bool operator==(const DERIVED& RHS) const { + return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr; + } + + bool operator!=(const DERIVED& RHS) const { + return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr; + } + + REFERENCE operator*() const { + return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr()); + } + + REFERENCE operator->() const { return operator*(); } +}; + +struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { + explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} + + StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {} + + StmtIterator(Decl** dgi, Decl** dge) + : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} + + StmtIterator(VariableArrayType* t) + : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} + + StmtIterator(Decl* D, Stmt **s = 0) + : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {} +}; + +struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, + const Stmt*> { + explicit ConstStmtIterator() : + StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {} + + ConstStmtIterator(const StmtIterator& RHS) : + StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.def b/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.def new file mode 100644 index 0000000..3a23e49 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.def @@ -0,0 +1,165 @@ +//===-- StmtNodes.def - Metadata about Stmt AST nodes -----------*- 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 AST Node info database. +// +//===---------------------------------------------------------------------===// + +#ifndef FIRST_STMT +#define FIRST_STMT(CLASS) +#define LAST_STMT(CLASS) +#endif + +#ifndef FIRST_EXPR +#define FIRST_EXPR(CLASS) +#define LAST_EXPR(CLASS) +#endif + +#ifndef EXPR +# define EXPR(Type, Base) STMT(Type, Base) +#endif + +#ifndef ABSTRACT_EXPR +# define ABSTRACT_EXPR(Type, Base) EXPR(Type, Base) +#endif + +// Normal Statements. +STMT(NullStmt , Stmt) +FIRST_STMT(NullStmt) +STMT(CompoundStmt , Stmt) +STMT(CaseStmt , SwitchCase) +STMT(DefaultStmt , SwitchCase) +STMT(LabelStmt , Stmt) +STMT(IfStmt , Stmt) +STMT(SwitchStmt , Stmt) +STMT(WhileStmt , Stmt) +STMT(DoStmt , Stmt) +STMT(ForStmt , Stmt) +STMT(GotoStmt , Stmt) +STMT(IndirectGotoStmt, Stmt) +STMT(ContinueStmt , Stmt) +STMT(BreakStmt , Stmt) +STMT(ReturnStmt , Stmt) +STMT(DeclStmt , Stmt) +STMT(SwitchCase , Stmt) + +// GNU Stmt Extensions +STMT(AsmStmt , Stmt) + +// Obj-C statements +STMT(ObjCAtTryStmt , Stmt) +STMT(ObjCAtCatchStmt , Stmt) +STMT(ObjCAtFinallyStmt , Stmt) +STMT(ObjCAtThrowStmt , Stmt) +STMT(ObjCAtSynchronizedStmt , Stmt) +// Obj-C2 statements +STMT(ObjCForCollectionStmt, Stmt) + +// C++ statements +STMT(CXXCatchStmt, Stmt) +STMT(CXXTryStmt , Stmt) + +LAST_STMT(CXXTryStmt) + +// Expressions. +ABSTRACT_EXPR(Expr , Stmt) +EXPR(PredefinedExpr , Expr) +EXPR(DeclRefExpr , Expr) +EXPR(IntegerLiteral , Expr) +EXPR(FloatingLiteral , Expr) +EXPR(ImaginaryLiteral , Expr) +EXPR(StringLiteral , Expr) +EXPR(CharacterLiteral , Expr) +EXPR(ParenExpr , Expr) +EXPR(UnaryOperator , Expr) +EXPR(OffsetOfExpr , Expr) +EXPR(SizeOfAlignOfExpr , Expr) +EXPR(ArraySubscriptExpr , Expr) +EXPR(CallExpr , Expr) +EXPR(MemberExpr , Expr) +ABSTRACT_EXPR(CastExpr , Expr) +EXPR(BinaryOperator , Expr) +EXPR(CompoundAssignOperator, BinaryOperator) +EXPR(ConditionalOperator , Expr) +EXPR(ImplicitCastExpr , CastExpr) +ABSTRACT_EXPR(ExplicitCastExpr, CastExpr) +EXPR(CStyleCastExpr , ExplicitCastExpr) +EXPR(CompoundLiteralExpr , Expr) +EXPR(ExtVectorElementExpr , Expr) +EXPR(InitListExpr , Expr) +EXPR(DesignatedInitExpr , Expr) +EXPR(ImplicitValueInitExpr , Expr) +EXPR(ParenListExpr , Expr) +EXPR(VAArgExpr , Expr) + +// GNU Extensions. +EXPR(AddrLabelExpr , Expr) +EXPR(StmtExpr , Expr) +EXPR(TypesCompatibleExpr , Expr) +EXPR(ChooseExpr , Expr) +EXPR(GNUNullExpr , Expr) + +// C++ Expressions. +EXPR(CXXOperatorCallExpr , CallExpr) +EXPR(CXXMemberCallExpr , CallExpr) +ABSTRACT_EXPR(CXXNamedCastExpr , ExplicitCastExpr) +EXPR(CXXStaticCastExpr , CXXNamedCastExpr) +EXPR(CXXDynamicCastExpr , CXXNamedCastExpr) +EXPR(CXXReinterpretCastExpr , CXXNamedCastExpr) +EXPR(CXXConstCastExpr , CXXNamedCastExpr) +EXPR(CXXFunctionalCastExpr , ExplicitCastExpr) +EXPR(CXXTypeidExpr , Expr) +EXPR(CXXBoolLiteralExpr , Expr) +EXPR(CXXNullPtrLiteralExpr , Expr) +EXPR(CXXThisExpr , Expr) +EXPR(CXXThrowExpr , Expr) +EXPR(CXXDefaultArgExpr , Expr) +EXPR(CXXZeroInitValueExpr , Expr) +EXPR(CXXNewExpr , Expr) +EXPR(CXXDeleteExpr , Expr) +EXPR(CXXPseudoDestructorExpr, Expr) +EXPR(UnresolvedLookupExpr , Expr) +EXPR(UnaryTypeTraitExpr , Expr) +EXPR(DependentScopeDeclRefExpr , Expr) +EXPR(CXXConstructExpr , Expr) +EXPR(CXXBindTemporaryExpr , Expr) +EXPR(CXXBindReferenceExpr , Expr) +EXPR(CXXExprWithTemporaries , Expr) +EXPR(CXXTemporaryObjectExpr , CXXConstructExpr) +EXPR(CXXUnresolvedConstructExpr, Expr) +EXPR(CXXDependentScopeMemberExpr, Expr) +EXPR(UnresolvedMemberExpr , Expr) + +// Obj-C Expressions. +EXPR(ObjCStringLiteral , Expr) +EXPR(ObjCEncodeExpr , Expr) +EXPR(ObjCMessageExpr , Expr) +EXPR(ObjCSelectorExpr , Expr) +EXPR(ObjCProtocolExpr , Expr) +EXPR(ObjCIvarRefExpr , Expr) +EXPR(ObjCPropertyRefExpr , Expr) +EXPR(ObjCImplicitSetterGetterRefExpr , Expr) +EXPR(ObjCSuperExpr , Expr) +EXPR(ObjCIsaExpr , Expr) + +// Clang Extensions. +EXPR(ShuffleVectorExpr , Expr) +EXPR(BlockExpr , Expr) +EXPR(BlockDeclRefExpr , Expr) + +FIRST_EXPR(PredefinedExpr) +LAST_EXPR(BlockDeclRefExpr) + +#undef ABSTRACT_EXPR +#undef EXPR +#undef STMT +#undef FIRST_STMT +#undef LAST_STMT +#undef FIRST_EXPR +#undef LAST_EXPR diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.td new file mode 100644 index 0000000..60c94a6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtNodes.td @@ -0,0 +1,127 @@ +class Stmt<bit abstract = 0> { + bit Abstract = abstract; +} + +class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> { + Stmt Base = base; +} + +// Statements +def NullStmt : Stmt; +def CompoundStmt : Stmt; +def LabelStmt : Stmt; +def IfStmt : Stmt; +def SwitchStmt : Stmt; +def WhileStmt : Stmt; +def DoStmt : Stmt; +def ForStmt : Stmt; +def GotoStmt : Stmt; +def IndirectGotoStmt : Stmt; +def ContinueStmt : Stmt; +def BreakStmt : Stmt; +def ReturnStmt : Stmt; +def DeclStmt : Stmt; +def SwitchCase : Stmt; +def CaseStmt : DStmt<SwitchCase>; +def DefaultStmt : DStmt<SwitchCase>; + +// GNU Extensions +def AsmStmt : Stmt; + +// Obj-C statements +def ObjCAtTryStmt : Stmt; +def ObjCAtCatchStmt : Stmt; +def ObjCAtFinallyStmt : Stmt; +def ObjCAtThrowStmt : Stmt; +def ObjCAtSynchronizedStmt : Stmt; +def ObjCForCollectionStmt : Stmt; + +// C++ statments +def CXXCatchStmt : Stmt; +def CXXTryStmt : Stmt; + +// Expressions +def Expr : Stmt<1>; +def PredefinedExpr : DStmt<Expr>; +def DeclRefExpr : DStmt<Expr>; +def IntegerLiteral : DStmt<Expr>; +def FloatingLiteral : DStmt<Expr>; +def ImaginaryLiteral : DStmt<Expr>; +def StringLiteral : DStmt<Expr>; +def CharacterLiteral : DStmt<Expr>; +def ParenExpr : DStmt<Expr>; +def UnaryOperator : DStmt<Expr>; +def OffsetOfExpr : DStmt<Expr>; +def SizeOfAlignOfExpr : DStmt<Expr>; +def ArraySubscriptExpr : DStmt<Expr>; +def CallExpr : DStmt<Expr>; +def MemberExpr : DStmt<Expr>; +def CastExpr : DStmt<Expr, 1>; +def BinaryOperator : DStmt<Expr>; +def CompoundAssignOperator : DStmt<BinaryOperator>; +def ConditionalOperator : DStmt<Expr>; +def ImplicitCastExpr : DStmt<CastExpr>; +def ExplicitCastExpr : DStmt<CastExpr, 1>; +def CStyleCastExpr : DStmt<ExplicitCastExpr>; +def CompoundLiteralExpr : DStmt<Expr>; +def ExtVectorElementExpr : DStmt<Expr>; +def InitListExpr : DStmt<Expr>; +def DesignatedInitExpr : DStmt<Expr>; +def ImplicitValueInitExpr : DStmt<Expr>; +def ParenListExpr : DStmt<Expr>; +def VAArgExpr : DStmt<Expr>; + +// GNU Extensions. +def AddrLabelExpr : DStmt<Expr>; +def StmtExpr : DStmt<Expr>; +def TypesCompatibleExpr : DStmt<Expr>; +def ChooseExpr : DStmt<Expr>; +def GNUNullExpr : DStmt<Expr>; + +// C++ Expressions. +def CXXOperatorCallExpr : DStmt<CallExpr>; +def CXXMemberCallExpr : DStmt<CallExpr>; +def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>; +def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>; +def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>; +def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>; +def CXXConstCastExpr : DStmt<CXXNamedCastExpr>; +def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>; +def CXXTypeidExpr : DStmt<Expr>; +def CXXBoolLiteralExpr : DStmt<Expr>; +def CXXNullPtrLiteralExpr : DStmt<Expr>; +def CXXThisExpr : DStmt<Expr>; +def CXXThrowExpr : DStmt<Expr>; +def CXXDefaultArgExpr : DStmt<Expr>; +def CXXZeroInitValueExpr : DStmt<Expr>; +def CXXNewExpr : DStmt<Expr>; +def CXXDeleteExpr : DStmt<Expr>; +def CXXPseudoDestructorExpr : DStmt<Expr>; +def UnresolvedLookupExpr : DStmt<Expr>; +def UnaryTypeTraitExpr : DStmt<Expr>; +def DependentScopeDeclRefExpr : DStmt<Expr>; +def CXXConstructExpr : DStmt<Expr>; +def CXXBindTemporaryExpr : DStmt<Expr>; +def CXXBindReferenceExpr : DStmt<Expr>; +def CXXExprWithTemporaries : DStmt<Expr>; +def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; +def CXXUnresolvedConstructExpr : DStmt<Expr>; +def CXXDependentScopeMemberExpr : DStmt<Expr>; +def UnresolvedMemberExpr : DStmt<Expr>; + +// Obj-C Expressions. +def ObjCStringLiteral : DStmt<Expr>; +def ObjCEncodeExpr : DStmt<Expr>; +def ObjCMessageExpr : DStmt<Expr>; +def ObjCSelectorExpr : DStmt<Expr>; +def ObjCProtocolExpr : DStmt<Expr>; +def ObjCIvarRefExpr : DStmt<Expr>; +def ObjCPropertyRefExpr : DStmt<Expr>; +def ObjCImplicitSetterGetterRefExpr : DStmt<Expr>; +def ObjCSuperExpr : DStmt<Expr>; +def ObjCIsaExpr : DStmt<Expr>; + +// Clang Extensions. +def ShuffleVectorExpr : DStmt<Expr>; +def BlockExpr : DStmt<Expr>; +def BlockDeclRefExpr : DStmt<Expr>; diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h new file mode 100644 index 0000000..269aa4c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h @@ -0,0 +1,344 @@ +//===--- StmtObjC.h - Classes for representing ObjC statements --*- 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 Objective-C statement AST node classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTOBJC_H +#define LLVM_CLANG_AST_STMTOBJC_H + +#include "clang/AST/Stmt.h" + +namespace clang { + +/// ObjCForCollectionStmt - This represents Objective-c's collection statement; +/// represented as 'for (element 'in' collection-expression)' stmt. +/// +class ObjCForCollectionStmt : public Stmt { + enum { ELEM, COLLECTION, BODY, END_EXPR }; + Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt. + SourceLocation ForLoc; + SourceLocation RParenLoc; +public: + ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, + SourceLocation FCL, SourceLocation RPL); + explicit ObjCForCollectionStmt(EmptyShell Empty) : + Stmt(ObjCForCollectionStmtClass, Empty) { } + + Stmt *getElement() { return SubExprs[ELEM]; } + Expr *getCollection() { + return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); + } + Stmt *getBody() { return SubExprs[BODY]; } + + const Stmt *getElement() const { return SubExprs[ELEM]; } + const Expr *getCollection() const { + return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); + } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setElement(Stmt *S) { SubExprs[ELEM] = S; } + void setCollection(Expr *E) { + SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E); + } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation Loc) { ForLoc = Loc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCForCollectionStmtClass; + } + static bool classof(const ObjCForCollectionStmt *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCAtCatchStmt - This represents objective-c's @catch statement. +class ObjCAtCatchStmt : public Stmt { +private: + VarDecl *ExceptionDecl; + Stmt *Body; + SourceLocation AtCatchLoc, RParenLoc; + +public: + ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, + VarDecl *catchVarDecl, + Stmt *atCatchStmt) + : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), + Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } + + explicit ObjCAtCatchStmt(EmptyShell Empty) : + Stmt(ObjCAtCatchStmtClass, Empty) { } + + const Stmt *getCatchBody() const { return Body; } + Stmt *getCatchBody() { return Body; } + void setCatchBody(Stmt *S) { Body = S; } + + const VarDecl *getCatchParamDecl() const { + return ExceptionDecl; + } + VarDecl *getCatchParamDecl() { + return ExceptionDecl; + } + void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } + + SourceLocation getAtCatchLoc() const { return AtCatchLoc; } + void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtCatchLoc, Body->getLocEnd()); + } + + bool hasEllipsis() const { return getCatchParamDecl() == 0; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAtCatchStmtClass; + } + static bool classof(const ObjCAtCatchStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement +class ObjCAtFinallyStmt : public Stmt { + Stmt *AtFinallyStmt; + SourceLocation AtFinallyLoc; +public: + ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt) + : Stmt(ObjCAtFinallyStmtClass), + AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {} + + explicit ObjCAtFinallyStmt(EmptyShell Empty) : + Stmt(ObjCAtFinallyStmtClass, Empty) { } + + const Stmt *getFinallyBody() const { return AtFinallyStmt; } + Stmt *getFinallyBody() { return AtFinallyStmt; } + void setFinallyBody(Stmt *S) { AtFinallyStmt = S; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); + } + + SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; } + void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAtFinallyStmtClass; + } + static bool classof(const ObjCAtFinallyStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCAtTryStmt - This represent objective-c's over-all +/// @try ... @catch ... @finally statement. +class ObjCAtTryStmt : public Stmt { +private: + // The location of the + SourceLocation AtTryLoc; + + // The number of catch blocks in this statement. + unsigned NumCatchStmts : 16; + + // Whether this statement has a @finally statement. + bool HasFinally : 1; + + /// \brief Retrieve the statements that are stored after this @try statement. + /// + /// The order of the statements in memory follows the order in the source, + /// with the @try body first, followed by the @catch statements (if any) and, + /// finally, the @finally (if it exists). + Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } + const Stmt* const *getStmts() const { + return reinterpret_cast<const Stmt * const*> (this + 1); + } + + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + + explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, + bool HasFinally) + : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), + HasFinally(HasFinally) { } + +public: + static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc, + Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + static ObjCAtTryStmt *CreateEmpty(ASTContext &Context, + unsigned NumCatchStmts, + bool HasFinally); + + /// \brief Retrieve the location of the @ in the @try. + SourceLocation getAtTryLoc() const { return AtTryLoc; } + void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } + + /// \brief Retrieve the @try body. + const Stmt *getTryBody() const { return getStmts()[0]; } + Stmt *getTryBody() { return getStmts()[0]; } + void setTryBody(Stmt *S) { getStmts()[0] = S; } + + /// \brief Retrieve the number of @catch statements in this try-catch-finally + /// block. + unsigned getNumCatchStmts() const { return NumCatchStmts; } + + /// \brief Retrieve a @catch statement. + const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); + } + + /// \brief Retrieve a @catch statement. + ObjCAtCatchStmt *getCatchStmt(unsigned I) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); + } + + /// \brief Set a particular catch statement. + void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + getStmts()[I + 1] = S; + } + + /// Retrieve the @finally statement, if any. + const ObjCAtFinallyStmt *getFinallyStmt() const { + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); + } + ObjCAtFinallyStmt *getFinallyStmt() { + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); + } + void setFinallyStmt(Stmt *S) { + assert(HasFinally && "@try does not have a @finally slot!"); + getStmts()[1 + NumCatchStmts] = S; + } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAtTryStmtClass; + } + static bool classof(const ObjCAtTryStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement. +/// Example: @synchronized (sem) { +/// do-something; +/// } +/// +class ObjCAtSynchronizedStmt : public Stmt { +private: + enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; + Stmt* SubStmts[END_EXPR]; + SourceLocation AtSynchronizedLoc; + +public: + ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, + Stmt *synchBody) + : Stmt(ObjCAtSynchronizedStmtClass) { + SubStmts[SYNC_EXPR] = synchExpr; + SubStmts[SYNC_BODY] = synchBody; + AtSynchronizedLoc = atSynchronizedLoc; + } + explicit ObjCAtSynchronizedStmt(EmptyShell Empty) : + Stmt(ObjCAtSynchronizedStmtClass, Empty) { } + + SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; } + void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; } + + const CompoundStmt *getSynchBody() const { + return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); + } + CompoundStmt *getSynchBody() { + return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]); + } + void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; } + + const Expr *getSynchExpr() const { + return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); + } + Expr *getSynchExpr() { + return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]); + } + void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; } + + virtual SourceRange getSourceRange() const { + return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAtSynchronizedStmtClass; + } + static bool classof(const ObjCAtSynchronizedStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// ObjCAtThrowStmt - This represents objective-c's @throw statement. +class ObjCAtThrowStmt : public Stmt { + Stmt *Throw; + SourceLocation AtThrowLoc; +public: + ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr) + : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) { + AtThrowLoc = atThrowLoc; + } + explicit ObjCAtThrowStmt(EmptyShell Empty) : + Stmt(ObjCAtThrowStmtClass, Empty) { } + + const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); } + Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); } + void setThrowExpr(Stmt *S) { Throw = S; } + + SourceLocation getThrowLoc() { return AtThrowLoc; } + void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } + + virtual SourceRange getSourceRange() const { + if (Throw) + return SourceRange(AtThrowLoc, Throw->getLocEnd()); + else + return SourceRange(AtThrowLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAtThrowStmtClass; + } + static bool classof(const ObjCAtThrowStmt *) { return true; } + + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h new file mode 100644 index 0000000..8078451 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h @@ -0,0 +1,177 @@ +//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- 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 StmtVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTVISITOR_H +#define LLVM_CLANG_AST_STMTVISITOR_H + +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S)) + +/// StmtVisitor - This class implements a simple visitor for Stmt subclasses. +/// Since Expr derives from Stmt, this also includes support for visiting Exprs. +template<typename ImplClass, typename RetTy=void> +class StmtVisitor { +public: + RetTy Visit(Stmt *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. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + default: assert(0 && "Unknown binary operator!"); + case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); + case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); + + case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator); + case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator); + case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator); + case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator); + case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator); + case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator); + + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); + case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); + case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); + case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator); + case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); + case BinaryOperator::MulAssign: + DISPATCH(BinMulAssign, CompoundAssignOperator); + case BinaryOperator::DivAssign: + DISPATCH(BinDivAssign, CompoundAssignOperator); + case BinaryOperator::RemAssign: + DISPATCH(BinRemAssign, CompoundAssignOperator); + case BinaryOperator::AddAssign: + DISPATCH(BinAddAssign, CompoundAssignOperator); + case BinaryOperator::SubAssign: + DISPATCH(BinSubAssign, CompoundAssignOperator); + case BinaryOperator::ShlAssign: + DISPATCH(BinShlAssign, CompoundAssignOperator); + case BinaryOperator::ShrAssign: + DISPATCH(BinShrAssign, CompoundAssignOperator); + case BinaryOperator::AndAssign: + DISPATCH(BinAndAssign, CompoundAssignOperator); + case BinaryOperator::OrAssign: + DISPATCH(BinOrAssign, CompoundAssignOperator); + case BinaryOperator::XorAssign: + DISPATCH(BinXorAssign, CompoundAssignOperator); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator); + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { + default: assert(0 && "Unknown unary operator!"); + case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator); + case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator); + case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator); + case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator); + case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); + case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator); + case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator); + case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator); + case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator); + case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator); + case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator); + case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator); + case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator); + case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator); + } + } + + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + default: assert(0 && "Unknown stmt kind!"); +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); +#include "clang/AST/StmtNodes.inc" + } + } + + // If the implementation chooses not to implement a certain visit method, fall + // back on VisitExpr or whatever else is the superclass. +#define STMT(CLASS, PARENT) \ + RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); } +#include "clang/AST/StmtNodes.inc" + + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. +#define BINOP_FALLBACK(NAME) \ + RetTy VisitBin ## NAME(BinaryOperator *S) { \ + DISPATCH(BinaryOperator, BinaryOperator); \ + } + BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) + BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) + BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) + BINOP_FALLBACK(Shr) + + BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) + BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) + BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) + BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) + + BINOP_FALLBACK(Assign) + BINOP_FALLBACK(Comma) +#undef BINOP_FALLBACK + + // If the implementation doesn't implement compound assignment operator + // methods, fall back on VisitCompoundAssignOperator. +#define CAO_FALLBACK(NAME) \ + RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \ + DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \ + } + CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) + CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) + CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) + CAO_FALLBACK(XorAssign) +#undef CAO_FALLBACK + + // If the implementation doesn't implement unary operator methods, fall back + // on VisitUnaryOperator. +#define UNARYOP_FALLBACK(NAME) \ + RetTy VisitUnary ## NAME(UnaryOperator *S) { \ + DISPATCH(UnaryOperator, UnaryOperator); \ + } + UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) + UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) + UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) + + UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) + UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) + UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) + UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) +#undef UNARYOP_FALLBACK + + // Base case, ignore it. :) + RetTy VisitStmt(Stmt *Node) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h new file mode 100644 index 0000000..8b38001 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h @@ -0,0 +1,482 @@ +//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides definitions which are common for all kinds of +// template representation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H +#define LLVM_CLANG_AST_TEMPLATEBASE_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" + +namespace llvm { + class FoldingSetNodeID; +} + +namespace clang { + +class Decl; +class DiagnosticBuilder; +class Expr; +class TypeSourceInfo; + +/// \brief Represents a template argument within a class template +/// specialization. +class TemplateArgument { + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + struct { + TemplateArgument *Args; + unsigned NumArgs; + bool CopyArgs; + } Args; + }; + +public: + /// \brief The type of template argument we're storing. + enum ArgKind { + /// \brief Represents an empty template argument, e.g., one that has not + /// been deduced. + Null = 0, + /// The template argument is a type. Its value is stored in the + /// TypeOrValue field. + Type, + /// The template argument is a declaration that was provided for a pointer + /// or reference non-type template parameter. + Declaration, + /// The template argument is an integral value stored in an llvm::APSInt + /// that was provided for an integral non-type template parameter. + Integral, + /// The template argument is a template name that was provided for a + /// template template parameter. + Template, + /// The template argument is a value- or type-dependent expression + /// stored in an Expr*. + Expression, + /// The template argument is actually a parameter pack. Arguments are stored + /// in the Args struct. + Pack + } Kind; + + /// \brief Construct an empty, invalid template argument. + TemplateArgument() : TypeOrValue(0), Kind(Null) { } + + /// \brief Construct a template type argument. + TemplateArgument(QualType T) : Kind(Type) { + TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + } + + /// \brief Construct a template argument that refers to a + /// declaration, which is either an external declaration or a + /// template declaration. + TemplateArgument(Decl *D) : Kind(Declaration) { + // FIXME: Need to be sure we have the "canonical" declaration! + TypeOrValue = reinterpret_cast<uintptr_t>(D); + } + + /// \brief Construct an integral constant template argument. + TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { + new (Integer.Value) llvm::APSInt(Value); + Integer.Type = Type.getAsOpaquePtr(); + } + + /// \brief Construct a template argument that is a template. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + TemplateArgument(TemplateName Name) : Kind(Template) { + TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + } + + /// \brief Construct a template argument that is an expression. + /// + /// This form of template argument only occurs in template argument + /// lists used for dependent types and for expression; it will not + /// occur in a non-dependent, canonical template argument list. + TemplateArgument(Expr *E) : Kind(Expression) { + TypeOrValue = reinterpret_cast<uintptr_t>(E); + } + + /// \brief Copy constructor for a template argument. + TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { + if (Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else if (Kind == Pack) { + Args.NumArgs = Other.Args.NumArgs; + Args.Args = new TemplateArgument[Args.NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = Other.Args.Args[I]; + } + else + TypeOrValue = Other.TypeOrValue; + } + + TemplateArgument& operator=(const TemplateArgument& Other) { + // FIXME: Does not provide the strong guarantee for exception + // safety. + using llvm::APSInt; + + // FIXME: Handle Packs + assert(Kind != Pack && "FIXME: Handle packs"); + assert(Other.Kind != Pack && "FIXME: Handle packs"); + + if (Kind == Other.Kind && Kind == Integral) { + // Copy integral values. + *this->getAsIntegral() = *Other.getAsIntegral(); + Integer.Type = Other.Integer.Type; + } else { + // Destroy the current integral value, if that's what we're holding. + if (Kind == Integral) + getAsIntegral()->~APSInt(); + + Kind = Other.Kind; + + if (Other.Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else + TypeOrValue = Other.TypeOrValue; + } + + return *this; + } + + ~TemplateArgument() { + using llvm::APSInt; + + if (Kind == Integral) + getAsIntegral()->~APSInt(); + else if (Kind == Pack && Args.CopyArgs) + delete[] Args.Args; + } + + /// \brief Return the kind of stored template argument. + ArgKind getKind() const { return Kind; } + + /// \brief Determine whether this template argument has no value. + bool isNull() const { return Kind == Null; } + + /// \brief Retrieve the template argument as a type. + QualType getAsType() const { + if (Kind != Type) + return QualType(); + + return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue)); + } + + /// \brief Retrieve the template argument as a declaration. + Decl *getAsDecl() const { + if (Kind != Declaration) + return 0; + return reinterpret_cast<Decl *>(TypeOrValue); + } + + /// \brief Retrieve the template argument as a template name. + TemplateName getAsTemplate() const { + if (Kind != Template) + return TemplateName(); + + return TemplateName::getFromVoidPointer( + reinterpret_cast<void *> (TypeOrValue)); + } + + /// \brief Retrieve the template argument as an integral value. + llvm::APSInt *getAsIntegral() { + if (Kind != Integral) + return 0; + return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); + } + + const llvm::APSInt *getAsIntegral() const { + return const_cast<TemplateArgument*>(this)->getAsIntegral(); + } + + /// \brief Retrieve the type of the integral value. + QualType getIntegralType() const { + if (Kind != Integral) + return QualType(); + + return QualType::getFromOpaquePtr(Integer.Type); + } + + void setIntegralType(QualType T) { + assert(Kind == Integral && + "Cannot set the integral type of a non-integral template argument"); + Integer.Type = T.getAsOpaquePtr(); + } + + /// \brief Retrieve the template argument as an expression. + Expr *getAsExpr() const { + if (Kind != Expression) + return 0; + + return reinterpret_cast<Expr *>(TypeOrValue); + } + + /// \brief Iterator that traverses the elements of a template argument pack. + typedef const TemplateArgument * pack_iterator; + + /// \brief Iterator referencing the first argument of a template argument + /// pack. + pack_iterator pack_begin() const { + assert(Kind == Pack); + return Args.Args; + } + + /// \brief Iterator referencing one past the last argument of a template + /// argument pack. + pack_iterator pack_end() const { + assert(Kind == Pack); + return Args.Args + Args.NumArgs; + } + + /// \brief The number of template arguments in the given template argument + /// pack. + unsigned pack_size() const { + assert(Kind == Pack); + return Args.NumArgs; + } + + /// \brief Construct a template argument pack. + void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); + + /// \brief Used to insert TemplateArguments into FoldingSets. + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const; +}; + +/// Location information for a TemplateArgument. +struct TemplateArgumentLocInfo { +private: + union { + Expr *Expression; + TypeSourceInfo *Declarator; + struct { + unsigned QualifierRange[2]; + unsigned TemplateNameLoc; + } Template; + }; + +#ifndef NDEBUG + enum Kind { + K_None, + K_TypeSourceInfo, + K_Expression, + K_Template + } Kind; +#endif + +public: + TemplateArgumentLocInfo() + : Expression(0) +#ifndef NDEBUG + , Kind(K_None) +#endif + {} + + TemplateArgumentLocInfo(TypeSourceInfo *TInfo) + : Declarator(TInfo) +#ifndef NDEBUG + , Kind(K_TypeSourceInfo) +#endif + {} + + TemplateArgumentLocInfo(Expr *E) + : Expression(E) +#ifndef NDEBUG + , Kind(K_Expression) +#endif + {} + + TemplateArgumentLocInfo(SourceRange QualifierRange, + SourceLocation TemplateNameLoc) +#ifndef NDEBUG + : Kind(K_Template) +#endif + { + Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); + Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + } + + TypeSourceInfo *getAsTypeSourceInfo() const { + assert(Kind == K_TypeSourceInfo); + return Declarator; + } + + Expr *getAsExpr() const { + assert(Kind == K_Expression); + return Expression; + } + + SourceRange getTemplateQualifierRange() const { + assert(Kind == K_Template); + return SourceRange( + SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), + SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + } + + SourceLocation getTemplateNameLoc() const { + assert(Kind == K_Template); + return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + } + +#ifndef NDEBUG + void validateForArgument(const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Type: + assert(Kind == K_TypeSourceInfo); + break; + case TemplateArgument::Expression: + case TemplateArgument::Declaration: + assert(Kind == K_Expression); + break; + case TemplateArgument::Template: + assert(Kind == K_Template); + break; + case TemplateArgument::Integral: + case TemplateArgument::Pack: + assert(Kind == K_None); + break; + case TemplateArgument::Null: + llvm_unreachable("source info for null template argument?"); + } + } +#endif +}; + +/// Location wrapper for a TemplateArgument. TemplateArgument is to +/// TemplateArgumentLoc as Type is to TypeLoc. +class TemplateArgumentLoc { + TemplateArgument Argument; + TemplateArgumentLocInfo LocInfo; + +public: + TemplateArgumentLoc() {} + + TemplateArgumentLoc(const TemplateArgument &Argument, + TemplateArgumentLocInfo Opaque) + : Argument(Argument), LocInfo(Opaque) { + } + + TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) + : Argument(Argument), LocInfo(TInfo) { + assert(Argument.getKind() == TemplateArgument::Type); + } + + TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) + : Argument(Argument), LocInfo(E) { + assert(Argument.getKind() == TemplateArgument::Expression); + } + + TemplateArgumentLoc(const TemplateArgument &Argument, + SourceRange QualifierRange, + SourceLocation TemplateNameLoc) + : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { + assert(Argument.getKind() == TemplateArgument::Template); + } + + /// \brief - Fetches the primary location of the argument. + SourceLocation getLocation() const { + if (Argument.getKind() == TemplateArgument::Template) + return getTemplateNameLoc(); + + return getSourceRange().getBegin(); + } + + /// \brief - Fetches the full source range of the argument. + SourceRange getSourceRange() const; + + const TemplateArgument &getArgument() const { + return Argument; + } + + TemplateArgumentLocInfo getLocInfo() const { + return LocInfo; + } + + TypeSourceInfo *getTypeSourceInfo() const { + assert(Argument.getKind() == TemplateArgument::Type); + return LocInfo.getAsTypeSourceInfo(); + } + + Expr *getSourceExpression() const { + assert(Argument.getKind() == TemplateArgument::Expression); + return LocInfo.getAsExpr(); + } + + Expr *getSourceDeclExpression() const { + assert(Argument.getKind() == TemplateArgument::Declaration); + return LocInfo.getAsExpr(); + } + + SourceRange getTemplateQualifierRange() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateQualifierRange(); + } + + SourceLocation getTemplateNameLoc() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateNameLoc(); + } +}; + +/// A convenient class for passing around template argument +/// information. Designed to be passed by reference. +class TemplateArgumentListInfo { + llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; + +public: + TemplateArgumentListInfo() {} + + TemplateArgumentListInfo(SourceLocation LAngleLoc, + SourceLocation RAngleLoc) + : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} + + SourceLocation getLAngleLoc() const { return LAngleLoc; } + SourceLocation getRAngleLoc() const { return RAngleLoc; } + + void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } + void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } + + unsigned size() const { return Arguments.size(); } + + const TemplateArgumentLoc *getArgumentArray() const { + return Arguments.data(); + } + + const TemplateArgumentLoc &operator[](unsigned I) const { + return Arguments[I]; + } + + void addArgument(const TemplateArgumentLoc &Loc) { + Arguments.push_back(Loc); + } +}; + +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const TemplateArgument &Arg); + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h new file mode 100644 index 0000000..2e3b6df --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h @@ -0,0 +1,372 @@ +//===--- TemplateName.h - C++ Template Name Representation-------*- 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 TemplateName interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATENAME_H +#define LLVM_CLANG_AST_TEMPLATENAME_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" +#include "clang/Basic/OperatorKinds.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +class DependentTemplateName; +class DiagnosticBuilder; +class IdentifierInfo; +class NestedNameSpecifier; +struct PrintingPolicy; +class QualifiedTemplateName; +class NamedDecl; +class TemplateDecl; + +/// \brief A structure for storing the information associated with an +/// overloaded template name. +class OverloadedTemplateStorage { + union { + unsigned Size; + NamedDecl *Storage[1]; + }; + + friend class ASTContext; + + OverloadedTemplateStorage(unsigned Size) : Size(Size) {} + + NamedDecl **getStorage() { + return &Storage[1]; + } + NamedDecl * const *getStorage() const { + return &Storage[1]; + } + +public: + typedef NamedDecl *const *iterator; + + unsigned size() const { return Size; } + + iterator begin() const { return getStorage(); } + iterator end() const { return getStorage() + size(); } +}; + +/// \brief Represents a C++ template name within the type system. +/// +/// A C++ template name refers to a template within the C++ type +/// system. In most cases, a template name is simply a reference to a +/// class template, e.g. +/// +/// \code +/// template<typename T> class X { }; +/// +/// X<int> xi; +/// \endcode +/// +/// Here, the 'X' in \c X<int> is a template name that refers to the +/// declaration of the class template X, above. Template names can +/// also refer to function templates, C++0x template aliases, etc. +/// +/// Some template names are dependent. For example, consider: +/// +/// \code +/// template<typename MetaFun, typename T1, typename T2> struct apply2 { +/// typedef typename MetaFun::template apply<T1, T2>::type type; +/// }; +/// \endcode +/// +/// Here, "apply" is treated as a template name within the typename +/// specifier in the typedef. "apply" is a nested template, and can +/// only be understood in the context of +class TemplateName { + typedef llvm::PointerUnion4<TemplateDecl *, + OverloadedTemplateStorage *, + QualifiedTemplateName *, + DependentTemplateName *> StorageType; + + StorageType Storage; + + explicit TemplateName(void *Ptr) { + Storage = StorageType::getFromOpaqueValue(Ptr); + } + +public: + TemplateName() : Storage() { } + explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } + explicit TemplateName(OverloadedTemplateStorage *Storage) + : Storage(Storage) { } + explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } + explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } + + /// \brief Determine whether this template name is NULL. + bool isNull() const { return Storage.isNull(); } + + /// \brief Retrieve the the underlying template declaration that + /// this template name refers to, if known. + /// + /// \returns The template declaration that this template name refers + /// to, if any. If the template name does not refer to a specific + /// declaration because it is a dependent name, or if it refers to a + /// set of function templates, returns NULL. + TemplateDecl *getAsTemplateDecl() const; + + /// \brief Retrieve the the underlying, overloaded function template + // declarations that this template name refers to, if known. + /// + /// \returns The set of overloaded function templates that this template + /// name refers to, if known. If the template name does not refer to a + /// specific set of function templates because it is a dependent name or + /// refers to a single template, returns NULL. + OverloadedTemplateStorage *getAsOverloadedTemplate() const { + return Storage.dyn_cast<OverloadedTemplateStorage *>(); + } + + /// \brief Retrieve the underlying qualified template name + /// structure, if any. + QualifiedTemplateName *getAsQualifiedTemplateName() const { + return Storage.dyn_cast<QualifiedTemplateName *>(); + } + + /// \brief Retrieve the underlying dependent template name + /// structure, if any. + DependentTemplateName *getAsDependentTemplateName() const { + return Storage.dyn_cast<DependentTemplateName *>(); + } + + /// \brief Determines whether this is a dependent template name. + bool isDependent() const; + + /// \brief Print the template name. + /// + /// \param OS the output stream to which the template name will be + /// printed. + /// + /// \param SuppressNNS if true, don't print the + /// nested-name-specifier that precedes the template name (if it has + /// one). + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, + bool SuppressNNS = false) const; + + /// \brief Debugging aid that dumps the template name to standard + /// error. + void dump() const; + + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddPointer(Storage.getOpaqueValue()); + } + + /// \brief Retrieve the template name as a void pointer. + void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } + + /// \brief Build a template name from a void pointer. + static TemplateName getFromVoidPointer(void *Ptr) { + return TemplateName(Ptr); + } +}; + +/// Insertion operator for diagnostics. This allows sending TemplateName's +/// into a diagnostic with <<. +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + TemplateName N); + +/// \brief Represents a template name that was expressed as a +/// qualified name. +/// +/// This kind of template name refers to a template name that was +/// preceded by a nested name specifier, e.g., \c std::vector. Here, +/// the nested name specifier is "std::" and the template name is the +/// declaration for "vector". The QualifiedTemplateName class is only +/// used to provide "sugar" for template names that were expressed +/// with a qualified name, and has no semantic meaning. In this +/// manner, it is to TemplateName what ElaboratedType is to Type, +/// providing extra syntactic sugar for downstream clients. +class QualifiedTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template name. + /// + /// The bit is used to indicate whether the "template" keyword was + /// present before the template name itself. Note that the + /// "template" keyword is always redundant in this case (otherwise, + /// the template name would be a dependent name and we would express + /// this name with DependentTemplateName). + llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; + + /// \brief The template declaration or set of overloaded function templates + /// that this qualified name refers to. + TemplateDecl *Template; + + friend class ASTContext; + + QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, + TemplateDecl *Template) + : Qualifier(NNS, TemplateKeyword? 1 : 0), + Template(Template) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + + /// \brief Whether the template name was prefixed by the "template" + /// keyword. + bool hasTemplateKeyword() const { return Qualifier.getInt(); } + + /// \brief The template declaration that this qualified name refers + /// to. + TemplateDecl *getDecl() const { return Template; } + + /// \brief The template declaration to which this qualified name + /// refers. + TemplateDecl *getTemplateDecl() const { return Template; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + bool TemplateKeyword, TemplateDecl *Template) { + ID.AddPointer(NNS); + ID.AddBoolean(TemplateKeyword); + ID.AddPointer(Template); + } +}; + +/// \brief Represents a dependent template name that cannot be +/// resolved prior to template instantiation. +/// +/// This kind of template name refers to a dependent template name, +/// including its nested name specifier (if any). For example, +/// DependentTemplateName can refer to "MetaFun::template apply", +/// where "MetaFun::" is the nested name specifier and "apply" is the +/// template name referenced. The "template" keyword is implied. +class DependentTemplateName : public llvm::FoldingSetNode { + /// \brief The nested name specifier that qualifies the template + /// name. + /// + /// The bit stored in this qualifier describes whether the \c Name field + /// is interpreted as an IdentifierInfo pointer (when clear) or as an + /// overloaded operator kind (when set). + llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier; + + /// \brief The dependent template name. + union { + /// \brief The identifier template name. + /// + /// Only valid when the bit on \c Qualifier is clear. + const IdentifierInfo *Identifier; + + /// \brief The overloaded operator name. + /// + /// Only valid when the bit on \c Qualifier is set. + OverloadedOperatorKind Operator; + }; + + /// \brief The canonical template name to which this dependent + /// template name refers. + /// + /// The canonical template name for a dependent template name is + /// another dependent template name whose nested name specifier is + /// canonical. + TemplateName CanonicalTemplateName; + + friend class ASTContext; + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Identifier) + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(this) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + const IdentifierInfo *Identifier, + TemplateName Canon) + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(Canon) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator) + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(this) { } + + DependentTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator, + TemplateName Canon) + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(Canon) { } + +public: + /// \brief Return the nested name specifier that qualifies this name. + NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + + /// \brief Determine whether this template name refers to an identifier. + bool isIdentifier() const { return !Qualifier.getInt(); } + + /// \brief Returns the identifier to which this template name refers. + const IdentifierInfo *getIdentifier() const { + assert(isIdentifier() && "Template name isn't an identifier?"); + return Identifier; + } + + /// \brief Determine whether this template name refers to an overloaded + /// operator. + bool isOverloadedOperator() const { return Qualifier.getInt(); } + + /// \brief Return the overloaded operator to which this template name refers. + OverloadedOperatorKind getOperator() const { + assert(isOverloadedOperator() && + "Template name isn't an overloaded operator?"); + return Operator; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + if (isIdentifier()) + Profile(ID, getQualifier(), getIdentifier()); + else + Profile(ID, getQualifier(), getOperator()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + const IdentifierInfo *Identifier) { + ID.AddPointer(NNS); + ID.AddBoolean(false); + ID.AddPointer(Identifier); + } + + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + OverloadedOperatorKind Operator) { + ID.AddPointer(NNS); + ID.AddBoolean(true); + ID.AddInteger(Operator); + } +}; + +} // end namespace clang. + +namespace llvm { + +/// \brief The clang::TemplateName class is effectively a pointer. +template<> +class PointerLikeTypeTraits<clang::TemplateName> { +public: + static inline void *getAsVoidPointer(clang::TemplateName TN) { + return TN.getAsVoidPointer(); + } + + static inline clang::TemplateName getFromVoidPointer(void *Ptr) { + return clang::TemplateName::getFromVoidPointer(Ptr); + } + + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm. + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h new file mode 100644 index 0000000..c24bddb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h @@ -0,0 +1,3527 @@ +//===--- Type.h - C Language Family Type Representation ---------*- 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 Type interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPE_H +#define LLVM_CLANG_AST_TYPE_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Linkage.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/type_traits.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" + +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; +namespace clang { + enum { + TypeAlignmentInBits = 3, + TypeAlignment = 1 << TypeAlignmentInBits + }; + class Type; + class ExtQuals; + class QualType; +} + +namespace llvm { + template <typename T> + class PointerLikeTypeTraits; + template<> + class PointerLikeTypeTraits< ::clang::Type*> { + public: + static inline void *getAsVoidPointer(::clang::Type *P) { return P; } + static inline ::clang::Type *getFromVoidPointer(void *P) { + return static_cast< ::clang::Type*>(P); + } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; + }; + template<> + class PointerLikeTypeTraits< ::clang::ExtQuals*> { + public: + static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } + static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { + return static_cast< ::clang::ExtQuals*>(P); + } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; + }; + + template <> + struct isPodLike<clang::QualType> { static const bool value = true; }; +} + +namespace clang { + class ASTContext; + class TypedefDecl; + class TemplateDecl; + class TemplateTypeParmDecl; + class NonTypeTemplateParmDecl; + class TemplateTemplateParmDecl; + class TagDecl; + class RecordDecl; + class CXXRecordDecl; + class EnumDecl; + class FieldDecl; + class ObjCInterfaceDecl; + class ObjCProtocolDecl; + class ObjCMethodDecl; + class UnresolvedUsingTypenameDecl; + class Expr; + class Stmt; + class SourceLocation; + class StmtIteratorBase; + class TemplateArgument; + class TemplateArgumentLoc; + class TemplateArgumentListInfo; + class Type; + class ElaboratedType; + struct PrintingPolicy; + + template <typename> class CanQual; + typedef CanQual<Type> CanQualType; + + // Provide forward declarations for all of the *Type classes +#define TYPE(Class, Base) class Class##Type; +#include "clang/AST/TypeNodes.def" + +/// Qualifiers - The collection of all-type qualifiers we support. +/// Clang supports five independent qualifiers: +/// * C99: const, volatile, and restrict +/// * Embedded C (TR18037): address spaces +/// * Objective C: the GC attributes (none, weak, or strong) +class Qualifiers { +public: + enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ. + Const = 0x1, + Restrict = 0x2, + Volatile = 0x4, + CVRMask = Const | Volatile | Restrict + }; + + enum GC { + GCNone = 0, + Weak, + Strong + }; + + enum { + /// The maximum supported address space number. + /// 24 bits should be enough for anyone. + MaxAddressSpace = 0xffffffu, + + /// The width of the "fast" qualifier mask. + FastWidth = 2, + + /// The fast qualifier mask. + FastMask = (1 << FastWidth) - 1 + }; + + Qualifiers() : Mask(0) {} + + static Qualifiers fromFastMask(unsigned Mask) { + Qualifiers Qs; + Qs.addFastQualifiers(Mask); + return Qs; + } + + static Qualifiers fromCVRMask(unsigned CVR) { + Qualifiers Qs; + Qs.addCVRQualifiers(CVR); + return Qs; + } + + // Deserialize qualifiers from an opaque representation. + static Qualifiers fromOpaqueValue(unsigned opaque) { + Qualifiers Qs; + Qs.Mask = opaque; + return Qs; + } + + // Serialize these qualifiers into an opaque representation. + unsigned getAsOpaqueValue() const { + return Mask; + } + + bool hasConst() const { return Mask & Const; } + void setConst(bool flag) { + Mask = (Mask & ~Const) | (flag ? Const : 0); + } + void removeConst() { Mask &= ~Const; } + void addConst() { Mask |= Const; } + + bool hasVolatile() const { return Mask & Volatile; } + void setVolatile(bool flag) { + Mask = (Mask & ~Volatile) | (flag ? Volatile : 0); + } + void removeVolatile() { Mask &= ~Volatile; } + void addVolatile() { Mask |= Volatile; } + + bool hasRestrict() const { return Mask & Restrict; } + void setRestrict(bool flag) { + Mask = (Mask & ~Restrict) | (flag ? Restrict : 0); + } + void removeRestrict() { Mask &= ~Restrict; } + void addRestrict() { Mask |= Restrict; } + + bool hasCVRQualifiers() const { return getCVRQualifiers(); } + unsigned getCVRQualifiers() const { return Mask & CVRMask; } + void setCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask = (Mask & ~CVRMask) | mask; + } + void removeCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask &= ~mask; + } + void removeCVRQualifiers() { + removeCVRQualifiers(CVRMask); + } + void addCVRQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); + Mask |= mask; + } + + bool hasObjCGCAttr() const { return Mask & GCAttrMask; } + GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); } + void setObjCGCAttr(GC type) { + Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift); + } + void removeObjCGCAttr() { setObjCGCAttr(GCNone); } + void addObjCGCAttr(GC type) { + assert(type); + setObjCGCAttr(type); + } + + bool hasAddressSpace() const { return Mask & AddressSpaceMask; } + unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + void setAddressSpace(unsigned space) { + assert(space <= MaxAddressSpace); + Mask = (Mask & ~AddressSpaceMask) + | (((uint32_t) space) << AddressSpaceShift); + } + void removeAddressSpace() { setAddressSpace(0); } + void addAddressSpace(unsigned space) { + assert(space); + setAddressSpace(space); + } + + // Fast qualifiers are those that can be allocated directly + // on a QualType object. + bool hasFastQualifiers() const { return getFastQualifiers(); } + unsigned getFastQualifiers() const { return Mask & FastMask; } + void setFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask = (Mask & ~FastMask) | mask; + } + void removeFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask &= ~mask; + } + void removeFastQualifiers() { + removeFastQualifiers(FastMask); + } + void addFastQualifiers(unsigned mask) { + assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); + Mask |= mask; + } + + /// hasNonFastQualifiers - Return true if the set contains any + /// qualifiers which require an ExtQuals node to be allocated. + bool hasNonFastQualifiers() const { return Mask & ~FastMask; } + Qualifiers getNonFastQualifiers() const { + Qualifiers Quals = *this; + Quals.setFastQualifiers(0); + return Quals; + } + + /// hasQualifiers - Return true if the set contains any qualifiers. + bool hasQualifiers() const { return Mask; } + bool empty() const { return !Mask; } + + /// \brief Add the qualifiers from the given set to this set. + void addQualifiers(Qualifiers Q) { + // If the other set doesn't have any non-boolean qualifiers, just + // bit-or it in. + if (!(Q.Mask & ~CVRMask)) + Mask |= Q.Mask; + else { + Mask |= (Q.Mask & CVRMask); + if (Q.hasAddressSpace()) + addAddressSpace(Q.getAddressSpace()); + if (Q.hasObjCGCAttr()) + addObjCGCAttr(Q.getObjCGCAttr()); + } + } + + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } + bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } + + operator bool() const { return hasQualifiers(); } + + Qualifiers &operator+=(Qualifiers R) { + addQualifiers(R); + return *this; + } + + // Union two qualifier sets. If an enumerated qualifier appears + // in both sets, use the one from the right. + friend Qualifiers operator+(Qualifiers L, Qualifiers R) { + L += R; + return L; + } + + std::string getAsString() const; + std::string getAsString(const PrintingPolicy &Policy) const { + std::string Buffer; + getAsStringInternal(Buffer, Policy); + return Buffer; + } + void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Mask); + } + +private: + + // bits: |0 1 2|3 .. 4|5 .. 31| + // |C R V|GCAttr|AddrSpace| + uint32_t Mask; + + static const uint32_t GCAttrMask = 0x18; + static const uint32_t GCAttrShift = 3; + static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask); + static const uint32_t AddressSpaceShift = 5; +}; + + +/// ExtQuals - We can encode up to three 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' and 'restrict' qualifiers in +/// two low bits on the QualType pointer; a third bit records whether +/// the pointer is an ExtQuals node. 'const' was chosen because it is +/// orders of magnitude more common than the other two qualifiers, in +/// both library and user code. It's relatively rare to see +/// 'restrict' in user code, but many standard C headers are saturated +/// with 'restrict' declarations, so that representing them efficiently +/// is a critical goal of this representation. +class ExtQuals : public llvm::FoldingSetNode { + // NOTE: changing the fast qualifiers should be straightforward as + // long as you don't make 'const' non-fast. + // 1. Qualifiers: + // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ). + // Fast qualifiers must occupy the low-order bits. + // b) Update Qualifiers::FastWidth and FastMask. + // 2. QualType: + // a) Update is{Volatile,Restrict}Qualified(), defined inline. + // b) Update remove{Volatile,Restrict}, defined near the end of + // this header. + // 3. ASTContext: + // a) Update get{Volatile,Restrict}Type. + + /// Context - the context to which this set belongs. We save this + /// here so that QualifierCollector can use it to reapply extended + /// qualifiers to an arbitrary type without requiring a context to + /// be pushed through every single API dealing with qualifiers. + ASTContext& Context; + + /// BaseType - the underlying type that this qualifies + const Type *BaseType; + + /// Quals - the immutable set of qualifiers applied by this + /// node; always contains extended qualifiers. + Qualifiers Quals; + +public: + ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals) + : Context(Context), BaseType(Base), Quals(Quals) + { + assert(Quals.hasNonFastQualifiers() + && "ExtQuals created with no fast qualifiers"); + assert(!Quals.hasFastQualifiers() + && "ExtQuals created with fast qualifiers"); + } + + Qualifiers getQualifiers() const { return Quals; } + + bool hasVolatile() const { return Quals.hasVolatile(); } + + bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); } + Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); } + + bool hasAddressSpace() const { return Quals.hasAddressSpace(); } + unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + + const Type *getBaseType() const { return BaseType; } + + ASTContext &getContext() const { return Context; } + +public: + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getBaseType(), Quals); + } + static void Profile(llvm::FoldingSetNodeID &ID, + const Type *BaseType, + Qualifiers Quals) { + assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!"); + ID.AddPointer(BaseType); + Quals.Profile(ID); + } +}; + +/// CallingConv - Specifies the calling convention that a function uses. +enum CallingConv { + CC_Default, + CC_C, // __attribute__((cdecl)) + CC_X86StdCall, // __attribute__((stdcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall // __attribute__((thiscall)) +}; + + +/// 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 +/// greatly reduces the number of nodes we need to allocate for types (for +/// example we only need one for 'int', 'const int', 'volatile int', +/// 'const volatile int', etc). +/// +/// As an added efficiency bonus, instead of making this a pair, we +/// just store the two bits we care about in the low bits of the +/// pointer. To handle the packing/unpacking, we make QualType be a +/// simple wrapper class that acts like a smart pointer. A third bit +/// indicates whether there are extended qualifiers present, in which +/// case the pointer points to a special structure. +class QualType { + // Thankfully, these are efficiently composable. + llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, + Qualifiers::FastWidth> Value; + + const ExtQuals *getExtQualsUnsafe() const { + return Value.getPointer().get<const ExtQuals*>(); + } + + const Type *getTypePtrUnsafe() const { + return Value.getPointer().get<const Type*>(); + } + + QualType getUnqualifiedTypeSlow() const; + + friend class QualifierCollector; +public: + QualType() {} + + QualType(const Type *Ptr, unsigned Quals) + : Value(Ptr, Quals) {} + QualType(const ExtQuals *Ptr, unsigned Quals) + : Value(Ptr, Quals) {} + + unsigned getLocalFastQualifiers() const { return Value.getInt(); } + void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } + + /// Retrieves a pointer to the underlying (unqualified) type. + /// This should really return a const Type, but it's not worth + /// changing all the users right now. + Type *getTypePtr() const { + if (hasLocalNonFastQualifiers()) + return const_cast<Type*>(getExtQualsUnsafe()->getBaseType()); + return const_cast<Type*>(getTypePtrUnsafe()); + } + + void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } + static QualType getFromOpaquePtr(void *Ptr) { + QualType T; + T.Value.setFromOpaqueValue(Ptr); + return T; + } + + Type &operator*() const { + return *getTypePtr(); + } + + Type *operator->() const { + return getTypePtr(); + } + + bool isCanonical() const; + bool isCanonicalAsParam() const; + + /// isNull - Return true if this QualType doesn't point to a type yet. + bool isNull() const { + return Value.getPointer().isNull(); + } + + /// \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 + /// "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 + /// "volatile" qualifier set, without looking through typedefs that may have + /// added "volatile" at a different level. + bool isLocalVolatileQualified() const { + return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); + } + + /// \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 at a different level. + bool hasLocalQualifiers() const { + return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); + } + + /// \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. + bool hasLocalNonFastQualifiers() const { + return Value.getPointer().is<const ExtQuals*>(); + } + + /// \brief Retrieve the set of qualifiers local to this particular QualType + /// instance, not including any qualifiers acquired through typedefs or + /// other sugar. + Qualifiers getLocalQualifiers() const { + Qualifiers Quals; + if (hasLocalNonFastQualifiers()) + Quals = getExtQualsUnsafe()->getQualifiers(); + Quals.addFastQualifiers(getLocalFastQualifiers()); + return Quals; + } + + /// \brief Retrieve the set of qualifiers applied to this type. + Qualifiers getQualifiers() const; + + /// \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 { + unsigned CVR = getLocalFastQualifiers(); + if (isLocalVolatileQualified()) + CVR |= Qualifiers::Volatile; + return CVR; + } + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// applied to this type. + unsigned getCVRQualifiers() const; + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// applied to this type, looking through any number of unqualified array + /// types to their element types' qualifiers. + unsigned getCVRQualifiersThroughArrayTypes() const; + + bool isConstant(ASTContext& Ctx) const { + return QualType::isConstant(*this, Ctx); + } + + // Don't promise in the API that anything besides 'const' can be + // easily added. + + /// addConst - add the specified type qualifier to this QualType. + void addConst() { + addFastQualifiers(Qualifiers::Const); + } + QualType withConst() const { + return withFastQualifiers(Qualifiers::Const); + } + + void addFastQualifiers(unsigned TQs) { + assert(!(TQs & ~Qualifiers::FastMask) + && "non-fast qualifier bits set in mask!"); + Value.setInt(Value.getInt() | TQs); + } + + // FIXME: The remove* functions are semantically broken, because they might + // not remove a qualifier stored on a typedef. Most of the with* functions + // have the same problem. + void removeConst(); + void removeVolatile(); + void removeRestrict(); + void removeCVRQualifiers(unsigned Mask); + + void removeFastQualifiers() { Value.setInt(0); } + void removeFastQualifiers(unsigned Mask) { + assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers"); + Value.setInt(Value.getInt() & ~Mask); + } + + // Creates a type with the given qualifiers in addition to any + // qualifiers already on this type. + QualType withFastQualifiers(unsigned TQs) const { + QualType T = *this; + T.addFastQualifiers(TQs); + return T; + } + + // Creates a type with exactly the given fast qualifiers, removing + // any existing fast qualifiers. + QualType withExactFastQualifiers(unsigned TQs) const { + return withoutFastQualifiers().withFastQualifiers(TQs); + } + + // Removes fast qualifiers, but leaves any extended qualifiers in place. + QualType withoutFastQualifiers() const { + QualType T = *this; + T.removeFastQualifiers(); + return T; + } + + /// \brief Return this type with all of the instance-specific qualifiers + /// removed, but without removing any qualifiers that may have been applied + /// through typedefs. + QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } + + /// \brief Return the unqualified form of the given type, which might be + /// desugared to eliminate qualifiers introduced via typedefs. + QualType getUnqualifiedType() const { + QualType T = getLocalUnqualifiedType(); + if (!T.hasQualifiers()) + return T; + + return getUnqualifiedTypeSlow(); + } + + bool isMoreQualifiedThan(QualType Other) const; + bool isAtLeastAsQualifiedAs(QualType Other) const; + QualType getNonReferenceType() 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 + /// to getting the canonical type, but it doesn't remove *all* typedefs. For + /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is + /// concrete. + /// + /// Qualifiers are left in place. + QualType getDesugaredType() const { + return QualType::getDesugaredType(*this); + } + + /// operator==/!= - Indicate whether the specified types and qualifiers are + /// identical. + friend bool operator==(const QualType &LHS, const QualType &RHS) { + return LHS.Value == RHS.Value; + } + friend bool operator!=(const QualType &LHS, const QualType &RHS) { + return LHS.Value != RHS.Value; + } + std::string getAsString() const; + + std::string getAsString(const PrintingPolicy &Policy) const { + std::string S; + getAsStringInternal(S, Policy); + return S; + } + void getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const; + + void dump(const char *s) const; + void dump() const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(getAsOpaquePtr()); + } + + /// getAddressSpace - Return the address space of this type. + inline unsigned getAddressSpace() const; + + /// GCAttrTypesAttr - Returns gc attribute of this type. + inline Qualifiers::GC getObjCGCAttr() const; + + /// isObjCGCWeak true when Type is objc's weak. + bool isObjCGCWeak() const { + return getObjCGCAttr() == Qualifiers::Weak; + } + + /// isObjCGCStrong true when Type is objc's strong. + bool isObjCGCStrong() const { + return getObjCGCAttr() == Qualifiers::Strong; + } + +private: + // These methods are implemented in a separate translation unit; + // "static"-ize them to avoid creating temporary QualTypes in the + // caller. + static bool isConstant(QualType T, ASTContext& Ctx); + static QualType getDesugaredType(QualType T); +}; + +} // end clang. + +namespace llvm { +/// Implement simplify_type for QualType, so that we can dyn_cast from QualType +/// to a specific Type class. +template<> struct simplify_type<const ::clang::QualType> { + typedef ::clang::Type* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::QualType &Val) { + return Val.getTypePtr(); + } +}; +template<> struct simplify_type< ::clang::QualType> + : public simplify_type<const ::clang::QualType> {}; + +// Teach SmallPtrSet that QualType is "basically a pointer". +template<> +class PointerLikeTypeTraits<clang::QualType> { +public: + static inline void *getAsVoidPointer(clang::QualType P) { + return P.getAsOpaquePtr(); + } + static inline clang::QualType getFromVoidPointer(void *P) { + return clang::QualType::getFromOpaquePtr(P); + } + // Various qualifiers go in low bits. + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +namespace clang { + +/// 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 +/// references. For example, consider: +/// +/// typedef int foo; +/// typedef foo* bar; +/// 'int *' 'foo *' 'bar' +/// +/// There will be a Type object created for 'int'. Since int is canonical, its +/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a +/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next +/// there is a PointerType that represents 'int*', which, like 'int', is +/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical +/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type +/// is also 'int*'. +/// +/// Non-canonical types are useful for emitting diagnostics, without losing +/// information about typedefs being used. Canonical types are useful for type +/// comparisons (they allow by-pointer equality tests) and useful for reasoning +/// about whether something has a particular form (e.g. is a function type), +/// because they implicitly, recursively, strip all typedefs out of a type. +/// +/// Types, once created, are immutable. +/// +class Type { +public: + enum TypeClass { +#define TYPE(Class, Base) Class, +#define LAST_TYPE(Class) TypeLast = Class, +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + TagFirst = Record, TagLast = Enum + }; + +private: + Type(const Type&); // DO NOT IMPLEMENT. + void operator=(const Type&); // DO NOT IMPLEMENT. + + QualType CanonicalType; + + /// TypeClass bitfield - Enum that specifies what subclass this belongs to. + unsigned TC : 8; + + /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). + /// Note that this should stay at the end of the ivars for Type so that + /// subclasses can pack their bitfields into the same word. + bool Dependent : 1; + + /// \brief Whether the linkage of this type is already known. + mutable bool LinkageKnown : 1; + + /// \brief Linkage of this type. + mutable unsigned CachedLinkage : 2; + +protected: + /// \brief Compute the linkage of this type. + virtual Linkage getLinkageImpl() const; + + enum { BitsRemainingInType = 20 }; + + // silence VC++ warning C4355: 'this' : used in base member initializer list + Type *this_() { return this; } + Type(TypeClass tc, QualType Canonical, bool dependent) + : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), + TC(tc), Dependent(dependent), LinkageKnown(false), + CachedLinkage(NoLinkage) {} + virtual ~Type() {} + virtual void Destroy(ASTContext& C); + friend class ASTContext; + +public: + TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } + + bool isCanonicalUnqualified() const { + return CanonicalType.getTypePtr() == this; + } + + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): + /// object types, function types, and incomplete types. + + /// \brief Determines whether the type describes an object in memory. + /// + /// Note that this definition of object type corresponds to the C++ + /// definition of object type, which includes incomplete types, as + /// opposed to the C definition (which does not include incomplete + /// types). + bool isObjectType() const; + + /// isIncompleteType - Return true if this is an incomplete type. + /// 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; + + /// isIncompleteOrObjectType - Return true if this is an incomplete or object + /// type, in other words, not a function type. + bool isIncompleteOrObjectType() const { + return !isFunctionType(); + } + + /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10). + bool isPODType() const; + + /// isLiteralType - Return true if this is a literal type + /// (C++0x [basic.types]p10) + bool isLiteralType() const; + + /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array + /// types that have a non-constant expression. This does not include "[]". + bool isVariablyModifiedType() const; + + /// Helper methods to distinguish type categories. All type predicates + /// operate on the canonical type, ignoring typedefs and qualifiers. + + /// isSpecificBuiltinType - Test for a particular builtin type. + bool isSpecificBuiltinType(unsigned K) 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) + bool isEnumeralType() const; + bool isBooleanType() const; + bool isCharType() const; + bool isWideCharType() const; + bool isAnyCharacterType() const; + bool isIntegralType() const; + + /// Floating point categories. + bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) + /// isComplexType() does *not* include complex integers (a GCC extension). + /// isComplexIntegerType() can be used to test for complex integers. + bool isComplexType() const; // C99 6.2.5p11 (complex) + bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. + bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) + bool isRealType() const; // C99 6.2.5p17 (real floating + integer) + bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) + bool isVoidType() const; // C99 6.2.5p19 + bool isDerivedType() const; // C99 6.2.5p20 + bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) + bool isAggregateType() const; + + // Type Predicates: Check to see if this type is structurally the specified + // type, ignoring typedefs and qualifiers. + bool isFunctionType() const; + bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); } + bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); } + bool isPointerType() const; + bool isAnyPointerType() const; // Any C pointer or ObjC object pointer + bool isBlockPointerType() const; + bool isVoidPointerType() const; + bool isReferenceType() const; + bool isLValueReferenceType() const; + bool isRValueReferenceType() const; + bool isFunctionPointerType() const; + bool isMemberPointerType() const; + bool isMemberFunctionPointerType() const; + bool isArrayType() const; + bool isConstantArrayType() const; + bool isIncompleteArrayType() const; + bool isVariableArrayType() const; + bool isDependentSizedArrayType() const; + bool isRecordType() const; + bool isClassType() const; + bool isStructureType() const; + bool isStructureOrClassType() const; + bool isUnionType() const; + bool isComplexIntegerType() const; // GCC _Complex integer type. + bool isVectorType() const; // GCC vector type. + bool isExtVectorType() const; // Extended vector type. + bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. + // FIXME: change this to 'raw' interface type, so we can used 'interface' type + // for the common case. + bool isObjCObjectType() const; // NSString or typeof(*(id)0) + bool isObjCQualifiedInterfaceType() const; // NSString<foo> + bool isObjCQualifiedIdType() const; // id<foo> + bool isObjCQualifiedClassType() const; // Class<foo> + bool isObjCIdType() const; // id + bool isObjCClassType() const; // Class + bool isObjCSelType() const; // Class + bool isObjCBuiltinType() const; // 'id' or 'Class' + bool isTemplateTypeParmType() const; // C++ template type parameter + bool isNullPtrType() const; // C++0x nullptr_t + + /// isDependentType - Whether this type is a dependent type, meaning + /// that its definition somehow depends on a template parameter + /// (C++ [temp.dep.type]). + bool isDependentType() const { return Dependent; } + bool isOverloadableType() const; + + /// \brief Determine wither this type is a C++ elaborated-type-specifier. + bool isElaboratedTypeSpecifier() 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 + /// interface types, as well as nullptr_t. + bool hasPointerRepresentation() const; + + /// hasObjCPointerRepresentation - Whether this type can represent + /// an objective pointer type for the purpose of GC'ability + bool hasObjCPointerRepresentation() const; + + // Type Checking Functions: Check to see if this type is structurally the + // specified type, ignoring typedefs and qualifiers, and return a pointer to + // the best type we can. + const RecordType *getAsStructureType() const; + /// NOTE: getAs*ArrayType are methods on ASTContext. + const RecordType *getAsUnionType() const; + const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. + // The following is a convenience method that returns an ObjCObjectPointerType + // for object declared using an interface. + const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; + const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; + const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; + 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 + /// type of a class template or class template partial specialization. + CXXRecordDecl *getAsCXXRecordDecl() const; + + // Member-template getAs<specific type>'. This scheme will eventually + // replace the specific getAsXXXX methods above. + // + // There are some specializations of this member template listed + // immediately following this class. + template <typename T> const T *getAs() const; + + /// getArrayElementTypeNoTypeQual - If this is an array type, return the + /// element type of the array, potentially with type qualifiers missing. + /// This method should never be used when type qualifiers are meaningful. + const Type *getArrayElementTypeNoTypeQual() const; + + /// getPointeeType - If this is a pointer, ObjC object pointer, or block + /// pointer, this returns the respective pointee. + QualType getPointeeType() const; + + /// getUnqualifiedDesugaredType() - Return the specified type with + /// any "sugar" removed from the type, removing any typedefs, + /// typeofs, etc., as well as any qualifiers. + const Type *getUnqualifiedDesugaredType() const; + + /// More type predicates useful for type checking/promotion + bool isPromotableIntegerType() const; // C99 6.3.1.1p2 + + /// isSignedIntegerType - Return true if this is an integer type that is + /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], + /// an enum decl which has a signed representation, or a vector of signed + /// integer element type. + 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], an enum + /// decl which has an unsigned representation, or a vector of unsigned integer + /// element type. + bool isUnsignedIntegerType() const; + + /// isConstantSizeType - Return true if this is not a variable sized type, + /// according to the rules of C99 6.7.5p3. It is not legal to call this on + /// incomplete types. + bool isConstantSizeType() const; + + /// isSpecifierType - Returns true if this type can be represented by some + /// set of type specifiers. + bool isSpecifierType() const; + + /// \brief Determine the linkage of this type. + Linkage getLinkage() 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; + static bool classof(const Type *) { return true; } +}; + +template <> inline const TypedefType *Type::getAs() const { + return dyn_cast<TypedefType>(this); +} + +// We can do canonical leaf types faster, because we don't have to +// worry about preserving child type decoration. +#define TYPE(Class, Base) +#define LEAF_TYPE(Class) \ +template <> inline const Class##Type *Type::getAs() const { \ + return dyn_cast<Class##Type>(CanonicalType); \ +} +#include "clang/AST/TypeNodes.def" + + +/// BuiltinType - This class is used for builtin types like 'int'. Builtin +/// types are always canonical and have a literal name field. +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. + 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, // This is 'wchar_t' for C++. + Short, + Int, + Long, + LongLong, + Int128, // __int128_t + + Float, Double, LongDouble, + + NullPtr, // This is the type of C++0x 'nullptr'. + + Overload, // This represents the type of an overloaded function declaration. + Dependent, // This represents the type of a type-dependent expression. + + UndeducedAuto, // In C++0x, this represents the type of an auto variable + // that has not been deduced yet. + + /// The primitive Objective C 'id' type. The type pointed to by the + /// user-visible 'id' type. Only ever shows up in an AST as the base + /// type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The type pointed to by the + /// user-visible 'Class' type. Only ever shows up in an AST as the + /// base type of an ObjCObjectType. + ObjCClass, + + ObjCSel // This represents the ObjC 'SEL' type. + }; +private: + Kind TypeKind; + +protected: + virtual Linkage getLinkageImpl() const; + +public: + BuiltinType(Kind K) + : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)), + TypeKind(K) {} + + Kind getKind() const { return TypeKind; } + const char *getName(const LangOptions &LO) const; + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + bool isInteger() const { + return TypeKind >= Bool && TypeKind <= Int128; + } + + bool isSignedInteger() const { + return TypeKind >= Char_S && TypeKind <= Int128; + } + + bool isUnsignedInteger() const { + return TypeKind >= Bool && TypeKind <= UInt128; + } + + bool isFloatingPoint() const { + return TypeKind >= Float && TypeKind <= LongDouble; + } + + static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } + static bool classof(const BuiltinType *) { return true; } +}; + +/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex +/// types (_Complex float etc) as well as the GCC integer complex extensions. +/// +class ComplexType : public Type, public llvm::FoldingSetNode { + QualType ElementType; + ComplexType(QualType Element, QualType CanonicalPtr) : + Type(Complex, CanonicalPtr, Element->isDependentType()), + ElementType(Element) { + } + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + QualType getElementType() const { return ElementType; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) { + ID.AddPointer(Element.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Complex; } + static bool classof(const ComplexType *) { return true; } +}; + +/// PointerType - C99 6.7.5.1 - Pointer Declarators. +/// +class PointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + + PointerType(QualType Pointee, QualType CanonicalPtr) : + Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) { + } + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + + QualType getPointeeType() const { return PointeeType; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } + static bool classof(const PointerType *) { return true; } +}; + +/// BlockPointerType - pointer to a block type. +/// This type is to represent types syntactically represented as +/// "void (^)(int)", etc. Pointee is required to always be a function type. +/// +class BlockPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; // Block is some kind of pointer type + BlockPointerType(QualType Pointee, QualType CanonicalCls) : + Type(BlockPointer, CanonicalCls, Pointee->isDependentType()), + PointeeType(Pointee) { + } + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + + // Get the pointee type. Pointee is required to always be a function type. + QualType getPointeeType() const { return PointeeType; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == BlockPointer; + } + static bool classof(const BlockPointerType *) { return true; } +}; + +/// ReferenceType - Base for LValueReferenceType and RValueReferenceType +/// +class ReferenceType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + + /// True if the type was originally spelled with an lvalue sigil. + /// This is never true of rvalue references but can also be false + /// on lvalue references because of C++0x [dcl.typedef]p9, + /// as follows: + /// + /// typedef int &ref; // lvalue, spelled lvalue + /// typedef int &&rvref; // rvalue + /// ref &a; // lvalue, inner ref, spelled lvalue + /// ref &&a; // lvalue, inner ref + /// rvref &a; // lvalue, inner ref, spelled lvalue + /// rvref &&a; // rvalue, inner ref + bool SpelledAsLValue; + + /// True if the inner type is a reference type. This only happens + /// in non-canonical forms. + bool InnerRef; + +protected: + ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) : + Type(tc, CanonicalRef, Referencee->isDependentType()), + PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), + InnerRef(Referencee->isReferenceType()) { + } + + virtual Linkage getLinkageImpl() const; + +public: + bool isSpelledAsLValue() const { return SpelledAsLValue; } + bool isInnerRef() const { return InnerRef; } + + QualType getPointeeTypeAsWritten() const { return PointeeType; } + QualType getPointeeType() const { + // FIXME: this might strip inner qualifiers; okay? + const ReferenceType *T = this; + while (T->InnerRef) + T = T->PointeeType->getAs<ReferenceType>(); + return T->PointeeType; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, PointeeType, SpelledAsLValue); + } + static void Profile(llvm::FoldingSetNodeID &ID, + QualType Referencee, + bool SpelledAsLValue) { + ID.AddPointer(Referencee.getAsOpaquePtr()); + ID.AddBoolean(SpelledAsLValue); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == LValueReference || + T->getTypeClass() == RValueReference; + } + static bool classof(const ReferenceType *) { return true; } +}; + +/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference +/// +class LValueReferenceType : public ReferenceType { + LValueReferenceType(QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) : + ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) + {} + friend class ASTContext; // ASTContext creates these +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == LValueReference; + } + static bool classof(const LValueReferenceType *) { return true; } +}; + +/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference +/// +class RValueReferenceType : public ReferenceType { + RValueReferenceType(QualType Referencee, QualType CanonicalRef) : + ReferenceType(RValueReference, Referencee, CanonicalRef, false) { + } + friend class ASTContext; // ASTContext creates these +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == RValueReference; + } + static bool classof(const RValueReferenceType *) { return true; } +}; + +/// MemberPointerType - C++ 8.3.3 - Pointers to members +/// +class MemberPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + /// The class of which the pointee is a member. Must ultimately be a + /// RecordType, but could be a typedef or a template parameter too. + const Type *Class; + + MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : + Type(MemberPointer, CanonicalPtr, + Cls->isDependentType() || Pointee->isDependentType()), + PointeeType(Pointee), Class(Cls) { + } + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + + QualType getPointeeType() const { return PointeeType; } + + const Type *getClass() const { return Class; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType(), getClass()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, + const Type *Class) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + ID.AddPointer(Class); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == MemberPointer; + } + static bool classof(const MemberPointerType *) { return true; } +}; + +/// ArrayType - C99 6.7.5.2 - Array Declarators. +/// +class ArrayType : public Type, public llvm::FoldingSetNode { +public: + /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4]) + /// an array with a static size (e.g. int X[static 4]), or an array + /// with a star size (e.g. int X[*]). + /// 'static' is only allowed on function parameters. + enum ArraySizeModifier { + Normal, Static, Star + }; +private: + /// ElementType - The element type of the array. + QualType ElementType; + + // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum + /// NOTE: These fields are packed into the bitfields space in the Type class. + unsigned SizeModifier : 2; + + /// IndexTypeQuals - Capture qualifiers in declarations like: + /// 'int X[static restrict 4]'. For function parameters only. + unsigned IndexTypeQuals : 3; + +protected: + // C++ [temp.dep.type]p1: + // A type is dependent if it is... + // - an array type constructed from any dependent type or whose + // size is specified by a constant expression that is + // value-dependent, + ArrayType(TypeClass tc, QualType et, QualType can, + ArraySizeModifier sm, unsigned tq) + : Type(tc, can, et->isDependentType() || tc == DependentSizedArray), + ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {} + + friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + +public: + QualType getElementType() const { return ElementType; } + ArraySizeModifier getSizeModifier() const { + return ArraySizeModifier(SizeModifier); + } + Qualifiers getIndexTypeQualifiers() const { + return Qualifiers::fromCVRMask(IndexTypeQuals); + } + unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; } + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArray || + T->getTypeClass() == VariableArray || + T->getTypeClass() == IncompleteArray || + T->getTypeClass() == DependentSizedArray; + } + static bool classof(const ArrayType *) { return true; } +}; + +/// ConstantArrayType - This class represents the canonical version of +/// C arrays with a specified constant size. For example, the canonical +/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element +/// type is 'int' and the size is 404. +class ConstantArrayType : public ArrayType { + llvm::APInt Size; // Allows us to unique the type. + + ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, + ArraySizeModifier sm, unsigned tq) + : ArrayType(ConstantArray, et, can, sm, tq), + Size(size) {} +protected: + ConstantArrayType(TypeClass tc, QualType et, QualType can, + const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) + : ArrayType(tc, et, can, sm, tq), Size(size) {} + friend class ASTContext; // ASTContext creates these. +public: + const llvm::APInt &getSize() const { return Size; } + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getSize(), + getSizeModifier(), getIndexTypeCVRQualifiers()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, + const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, + unsigned TypeQuals) { + ID.AddPointer(ET.getAsOpaquePtr()); + ID.AddInteger(ArraySize.getZExtValue()); + ID.AddInteger(SizeMod); + ID.AddInteger(TypeQuals); + } + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArray; + } + static bool classof(const ConstantArrayType *) { return true; } +}; + +/// IncompleteArrayType - This class represents C arrays with an unspecified +/// size. For example 'int A[]' has an IncompleteArrayType where the element +/// type is 'int' and the size is unspecified. +class IncompleteArrayType : public ArrayType { + + IncompleteArrayType(QualType et, QualType can, + ArraySizeModifier sm, unsigned tq) + : ArrayType(IncompleteArray, et, can, sm, tq) {} + friend class ASTContext; // ASTContext creates these. +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == IncompleteArray; + } + static bool classof(const IncompleteArrayType *) { return true; } + + friend class StmtIteratorBase; + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getSizeModifier(), + getIndexTypeCVRQualifiers()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, + ArraySizeModifier SizeMod, unsigned TypeQuals) { + ID.AddPointer(ET.getAsOpaquePtr()); + ID.AddInteger(SizeMod); + ID.AddInteger(TypeQuals); + } +}; + +/// VariableArrayType - This class represents C arrays with a specified size +/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'. +/// Since the size expression is an arbitrary expression, we store it as such. +/// +/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and +/// should not be: two lexically equivalent variable array types could mean +/// different things, for example, these variables do not have the same type +/// dynamically: +/// +/// void foo(int x) { +/// int Y[x]; +/// ++x; +/// int Z[x]; +/// } +/// +class VariableArrayType : public ArrayType { + /// SizeExpr - An assignment expression. VLA's are only permitted within + /// a function block. + Stmt *SizeExpr; + /// Brackets - The left and right array brackets. + SourceRange Brackets; + + VariableArrayType(QualType et, QualType can, Expr *e, + ArraySizeModifier sm, unsigned tq, + SourceRange brackets) + : ArrayType(VariableArray, et, can, sm, tq), + SizeExpr((Stmt*) e), Brackets(brackets) {} + friend class ASTContext; // ASTContext creates these. + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { + // We use C-style casts instead of cast<> here because we do not wish + // to have a dependency of Type.h on Stmt.h/Expr.h. + return (Expr*) SizeExpr; + } + SourceRange getBracketsRange() const { return Brackets; } + SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } + SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == VariableArray; + } + static bool classof(const VariableArrayType *) { return true; } + + friend class StmtIteratorBase; + + void Profile(llvm::FoldingSetNodeID &ID) { + assert(0 && "Cannnot unique VariableArrayTypes."); + } +}; + +/// DependentSizedArrayType - This type represents an array type in +/// C++ whose size is a value-dependent expression. For example: +/// +/// \code +/// template<typename T, int Size> +/// class array { +/// T data[Size]; +/// }; +/// \endcode +/// +/// For these types, we won't actually know what the array bound is +/// until template instantiation occurs, at which point this will +/// become either a ConstantArrayType or a VariableArrayType. +class DependentSizedArrayType : public ArrayType { + ASTContext &Context; + + /// \brief An assignment expression that will instantiate to the + /// size of the array. + /// + /// The expression itself might be NULL, in which case the array + /// type will have its size deduced from an initializer. + Stmt *SizeExpr; + + /// Brackets - The left and right array brackets. + SourceRange Brackets; + + DependentSizedArrayType(ASTContext &Context, QualType et, QualType can, + Expr *e, ArraySizeModifier sm, unsigned tq, + SourceRange brackets) + : ArrayType(DependentSizedArray, et, can, sm, tq), + Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} + friend class ASTContext; // ASTContext creates these. + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { + // We use C-style casts instead of cast<> here because we do not wish + // to have a dependency of Type.h on Stmt.h/Expr.h. + return (Expr*) SizeExpr; + } + SourceRange getBracketsRange() const { return Brackets; } + SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } + SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentSizedArray; + } + static bool classof(const DependentSizedArrayType *) { return true; } + + friend class StmtIteratorBase; + + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), + getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + QualType ET, ArraySizeModifier SizeMod, + unsigned TypeQuals, Expr *E); +}; + +/// DependentSizedExtVectorType - This type represent an extended vector type +/// where either the type or size is dependent. For example: +/// @code +/// template<typename T, int Size> +/// class vector { +/// typedef T __attribute__((ext_vector_type(Size))) type; +/// } +/// @endcode +class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { + ASTContext &Context; + Expr *SizeExpr; + /// ElementType - The element type of the array. + QualType ElementType; + SourceLocation loc; + + DependentSizedExtVectorType(ASTContext &Context, QualType ElementType, + QualType can, Expr *SizeExpr, SourceLocation loc) + : Type (DependentSizedExtVector, can, true), + Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), + loc(loc) {} + friend class ASTContext; + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return loc; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentSizedExtVector; + } + static bool classof(const DependentSizedExtVectorType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + QualType ElementType, Expr *SizeExpr); +}; + + +/// VectorType - GCC generic vector type. This type is created using +/// __attribute__((vector_size(n)), where "n" specifies the vector size in +/// bytes; or from an Altivec __vector or vector declaration. +/// Since the constructor takes the number of vector elements, the +/// client is responsible for converting the size into the number of elements. +class VectorType : public Type, public llvm::FoldingSetNode { +protected: + /// ElementType - The element type of the vector. + QualType ElementType; + + /// NumElements - The number of elements in the vector. + unsigned NumElements; + + /// AltiVec - True if this is for an Altivec vector. + bool AltiVec; + + /// Pixel - True if this is for an Altivec vector pixel. + bool Pixel; + + VectorType(QualType vecType, unsigned nElements, QualType canonType, + bool isAltiVec, bool isPixel) : + Type(Vector, canonType, vecType->isDependentType()), + ElementType(vecType), NumElements(nElements), + AltiVec(isAltiVec), Pixel(isPixel) {} + VectorType(TypeClass tc, QualType vecType, unsigned nElements, + QualType canonType, bool isAltiVec, bool isPixel) + : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), + NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} + friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + +public: + + QualType getElementType() const { return ElementType; } + unsigned getNumElements() const { return NumElements; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + bool isAltiVec() const { return AltiVec; } + + bool isPixel() const { return Pixel; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getNumElements(), getTypeClass(), + AltiVec, Pixel); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, + unsigned NumElements, TypeClass TypeClass, + bool isAltiVec, bool isPixel) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + ID.AddInteger(NumElements); + ID.AddInteger(TypeClass); + ID.AddBoolean(isAltiVec); + ID.AddBoolean(isPixel); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; + } + static bool classof(const VectorType *) { return true; } +}; + +/// ExtVectorType - Extended vector type. This type is created using +/// __attribute__((ext_vector_type(n)), where "n" is the number of elements. +/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This +/// class enables syntactic extensions, like Vector Components for accessing +/// points, colors, and textures (modeled after OpenGL Shading Language). +class ExtVectorType : public VectorType { + ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : + VectorType(ExtVector, vecType, nElements, canonType, false, false) {} + friend class ASTContext; // ASTContext creates these. +public: + static int getPointAccessorIdx(char c) { + switch (c) { + default: return -1; + case 'x': return 0; + case 'y': return 1; + case 'z': return 2; + case 'w': return 3; + } + } + static int getNumericAccessorIdx(char c) { + switch (c) { + default: return -1; + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'A': + case 'a': return 10; + case 'B': + case 'b': return 11; + case 'C': + case 'c': return 12; + case 'D': + case 'd': return 13; + case 'E': + case 'e': return 14; + case 'F': + case 'f': return 15; + } + } + + static int getAccessorIdx(char c) { + if (int idx = getPointAccessorIdx(c)+1) return idx-1; + return getNumericAccessorIdx(c); + } + + bool isAccessorWithinNumElements(char c) const { + if (int idx = getAccessorIdx(c)+1) + return unsigned(idx-1) < NumElements; + return false; + } + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == ExtVector; + } + static bool classof(const ExtVectorType *) { return true; } +}; + +/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base +/// class of FunctionNoProtoType and FunctionProtoType. +/// +class FunctionType : public Type { + virtual void ANCHOR(); // Key function for FunctionType. + + /// SubClassData - This field is owned by the subclass, put here to pack + /// tightly with the ivars in Type. + bool SubClassData : 1; + + /// TypeQuals - Used only by FunctionProtoType, put here to pack with the + /// other bitfields. + /// The qualifiers are part of FunctionProtoType because... + /// + /// 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; + + /// NoReturn - Indicates if the function type is attribute noreturn. + unsigned NoReturn : 1; + + /// RegParm - How many arguments to pass inreg. + unsigned RegParm : 3; + + /// CallConv - The calling convention used by the function. + unsigned CallConv : 3; + + // The type returned by the function. + QualType ResultType; + + public: + // This class is used for passing arround the information needed to + // construct a call. It is not actually used for storage, just for + // factoring together common arguments. + // If you add a field (say Foo), other than the obvious places (both, constructors, + // compile failures), what you need to update is + // * Operetor== + // * getFoo + // * withFoo + // * functionType. Add Foo, getFoo. + // * ASTContext::getFooType + // * ASTContext::mergeFunctionTypes + // * FunctionNoProtoType::Profile + // * FunctionProtoType::Profile + // * TypePrinter::PrintFunctionProto + // * PCH read and write + // * Codegen + + class ExtInfo { + public: + // Constructor with no defaults. Use this when you know that you + // have all the elements (when reading a PCH file for example). + ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : + NoReturn(noReturn), RegParm(regParm), CC(cc) {} + + // Constructor with all defaults. Use when for example creating a + // function know to use defaults. + ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {} + + bool getNoReturn() const { return NoReturn; } + unsigned getRegParm() const { return RegParm; } + CallingConv getCC() const { return CC; } + + bool operator==(const ExtInfo &Other) const { + return getNoReturn() == Other.getNoReturn() && + getRegParm() == Other.getRegParm() && + getCC() == Other.getCC(); + } + bool operator!=(const ExtInfo &Other) const { + return !(*this == Other); + } + + // Note that we don't have setters. That is by design, use + // the following with methods instead of mutating these objects. + + ExtInfo withNoReturn(bool noReturn) const { + return ExtInfo(noReturn, getRegParm(), getCC()); + } + + ExtInfo withRegParm(unsigned RegParm) const { + return ExtInfo(getNoReturn(), RegParm, getCC()); + } + + ExtInfo withCallingConv(CallingConv cc) const { + return ExtInfo(getNoReturn(), getRegParm(), cc); + } + + private: + // True if we have __attribute__((noreturn)) + bool NoReturn; + // The value passed to __attribute__((regparm(x))) + unsigned RegParm; + // The calling convention as specified via + // __attribute__((cdecl|stdcall|fastcall|thiscall)) + CallingConv CC; + }; + +protected: + FunctionType(TypeClass tc, QualType res, bool SubclassInfo, + unsigned typeQuals, QualType Canonical, bool Dependent, + const ExtInfo &Info) + : Type(tc, Canonical, Dependent), + SubClassData(SubclassInfo), TypeQuals(typeQuals), + NoReturn(Info.getNoReturn()), + RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {} + bool getSubClassData() const { return SubClassData; } + unsigned getTypeQuals() const { return TypeQuals; } +public: + + QualType getResultType() const { return ResultType; } + unsigned getRegParmType() const { return RegParm; } + bool getNoReturnAttr() const { return NoReturn; } + CallingConv getCallConv() const { return (CallingConv)CallConv; } + ExtInfo getExtInfo() const { + return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv); + } + + static llvm::StringRef getNameForCallConv(CallingConv CC); + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionNoProto || + T->getTypeClass() == FunctionProto; + } + static bool classof(const FunctionType *) { return true; } +}; + +/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has +/// no information available about its arguments. +class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { + FunctionNoProtoType(QualType Result, QualType Canonical, + const ExtInfo &Info) + : FunctionType(FunctionNoProto, Result, false, 0, Canonical, + /*Dependent=*/false, Info) {} + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + // No additional state past what FunctionType provides. + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getResultType(), getExtInfo()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, + const ExtInfo &Info) { + ID.AddInteger(Info.getCC()); + ID.AddInteger(Info.getRegParm()); + ID.AddInteger(Info.getNoReturn()); + ID.AddPointer(ResultType.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionNoProto; + } + static bool classof(const FunctionNoProtoType *) { return true; } +}; + +/// FunctionProtoType - Represents a prototype with argument type info, e.g. +/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no +/// arguments, not as having a single void argument. Such a type can have an +/// exception specification, but this specification is not part of the canonical +/// type. +class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { + /// hasAnyDependentType - Determine whether there are any dependent + /// types within the arguments passed in. + static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) { + for (unsigned Idx = 0; Idx < numArgs; ++Idx) + if (ArgArray[Idx]->isDependentType()) + return true; + + return false; + } + + FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs, + bool isVariadic, unsigned typeQuals, bool hasExs, + bool hasAnyExs, const QualType *ExArray, + unsigned numExs, QualType Canonical, + const ExtInfo &Info) + : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical, + (Result->isDependentType() || + hasAnyDependentType(ArgArray, numArgs)), + Info), + NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs), + AnyExceptionSpec(hasAnyExs) { + // Fill in the trailing argument array. + QualType *ArgInfo = reinterpret_cast<QualType*>(this+1); + for (unsigned i = 0; i != numArgs; ++i) + ArgInfo[i] = ArgArray[i]; + // Fill in the exception array. + QualType *Ex = ArgInfo + numArgs; + for (unsigned i = 0; i != numExs; ++i) + Ex[i] = ExArray[i]; + } + + /// NumArgs - The number of arguments this function has, not counting '...'. + unsigned NumArgs : 20; + + /// NumExceptions - The number of types in the exception spec, if any. + unsigned NumExceptions : 10; + + /// HasExceptionSpec - Whether this function has an exception spec at all. + bool HasExceptionSpec : 1; + + /// AnyExceptionSpec - Whether this function has a throw(...) spec. + bool AnyExceptionSpec : 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. + + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + unsigned getNumArgs() const { return NumArgs; } + QualType getArgType(unsigned i) const { + assert(i < NumArgs && "Invalid argument number!"); + return arg_type_begin()[i]; + } + + bool hasExceptionSpec() const { return HasExceptionSpec; } + bool hasAnyExceptionSpec() const { return AnyExceptionSpec; } + unsigned getNumExceptions() const { return NumExceptions; } + QualType getExceptionType(unsigned i) const { + assert(i < NumExceptions && "Invalid exception number!"); + return exception_begin()[i]; + } + bool hasEmptyExceptionSpec() const { + return hasExceptionSpec() && !hasAnyExceptionSpec() && + getNumExceptions() == 0; + } + + bool isVariadic() const { return getSubClassData(); } + unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } + + typedef const QualType *arg_type_iterator; + arg_type_iterator arg_type_begin() const { + return reinterpret_cast<const QualType *>(this+1); + } + arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; } + + typedef const QualType *exception_iterator; + exception_iterator exception_begin() const { + // exceptions begin where arguments end + return arg_type_end(); + } + exception_iterator exception_end() const { + return exception_begin() + NumExceptions; + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == FunctionProto; + } + static bool classof(const FunctionProtoType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, + arg_type_iterator ArgTys, unsigned NumArgs, + bool isVariadic, unsigned TypeQuals, + bool hasExceptionSpec, bool anyExceptionSpec, + unsigned NumExceptions, exception_iterator Exs, + const ExtInfo &ExtInfo); +}; + + +/// \brief Represents the dependent type named by a dependently-scoped +/// typename using declaration, e.g. +/// using typename Base<T>::foo; +/// Template instantiation turns these into the underlying type. +class UnresolvedUsingType : public Type { + UnresolvedUsingTypenameDecl *Decl; + + UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) + : Type(UnresolvedUsing, QualType(), true), + Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} + friend class ASTContext; // ASTContext creates these. +public: + + UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == UnresolvedUsing; + } + static bool classof(const UnresolvedUsingType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + return Profile(ID, Decl); + } + static void Profile(llvm::FoldingSetNodeID &ID, + UnresolvedUsingTypenameDecl *D) { + ID.AddPointer(D); + } +}; + + +class TypedefType : public Type { + TypedefDecl *Decl; +protected: + TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + : Type(tc, can, can->isDependentType()), + Decl(const_cast<TypedefDecl*>(D)) { + assert(!isa<TypedefType>(can) && "Invalid canonical type"); + } + friend class ASTContext; // ASTContext creates these. +public: + + TypedefDecl *getDecl() const { return Decl; } + + /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to + /// potentially looking through *all* consecutive typedefs. This returns the + /// sum of the type qualifiers, so if you have: + /// typedef const int A; + /// typedef volatile A B; + /// looking through the typedefs for B will give you "const volatile A". + QualType LookThroughTypedefs() const; + + bool isSugared() const { return true; } + QualType desugar() const; + + static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } + static bool classof(const TypedefType *) { return true; } +}; + +/// TypeOfExprType (GCC extension). +class TypeOfExprType : public Type { + Expr *TOExpr; + +protected: + TypeOfExprType(Expr *E, QualType can = QualType()); + friend class ASTContext; // ASTContext creates these. +public: + Expr *getUnderlyingExpr() const { return TOExpr; } + + /// \brief Remove a single level of sugar. + QualType desugar() const; + + /// \brief Returns whether this type directly provides sugar. + bool isSugared() const { return true; } + + static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } + static bool classof(const TypeOfExprType *) { return true; } +}; + +/// \brief Internal representation of canonical, dependent +/// typeof(expr) types. +/// +/// This class is used internally by the ASTContext to manage +/// canonical, dependent types, only. Clients will only see instances +/// of this class via TypeOfExprType nodes. +class DependentTypeOfExprType + : public TypeOfExprType, public llvm::FoldingSetNode { + ASTContext &Context; + +public: + DependentTypeOfExprType(ASTContext &Context, Expr *E) + : TypeOfExprType(E), Context(Context) { } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getUnderlyingExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + Expr *E); +}; + +/// TypeOfType (GCC extension). +class TypeOfType : public Type { + QualType TOType; + TypeOfType(QualType T, QualType can) + : Type(TypeOf, can, T->isDependentType()), TOType(T) { + assert(!isa<TypedefType>(can) && "Invalid canonical type"); + } + friend class ASTContext; // ASTContext creates these. +public: + QualType getUnderlyingType() const { return TOType; } + + /// \brief Remove a single level of sugar. + QualType desugar() const { return getUnderlyingType(); } + + /// \brief Returns whether this type directly provides sugar. + bool isSugared() const { return true; } + + static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } + static bool classof(const TypeOfType *) { return true; } +}; + +/// 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: + DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType()); + friend class ASTContext; // ASTContext creates these. +public: + Expr *getUnderlyingExpr() const { return E; } + QualType getUnderlyingType() const { return UnderlyingType; } + + /// \brief Remove a single level of sugar. + QualType desugar() const { return getUnderlyingType(); } + + /// \brief Returns whether this type directly provides sugar. + bool isSugared() const { return !isDependentType(); } + + static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } + static bool classof(const DecltypeType *) { return true; } +}; + +/// \brief Internal representation of canonical, dependent +/// decltype(expr) types. +/// +/// This class is used internally by the ASTContext to manage +/// canonical, dependent types, only. Clients will only see instances +/// of this class via DecltypeType nodes. +class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { + ASTContext &Context; + +public: + DependentDecltypeType(ASTContext &Context, Expr *E); + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getUnderlyingExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + Expr *E); +}; + +class TagType : public Type { + /// Stores the TagDecl associated with this type. The decl will + /// point to the TagDecl that actually defines the entity (or is a + /// definition in progress), if there is such a definition. The + /// single-bit value will be non-zero when this tag is in the + /// process of being defined. + mutable llvm::PointerIntPair<TagDecl *, 1> decl; + friend class ASTContext; + friend class TagDecl; + +protected: + TagType(TypeClass TC, const TagDecl *D, QualType can); + + virtual Linkage getLinkageImpl() const; + +public: + TagDecl *getDecl() const { return decl.getPointer(); } + + /// @brief Determines whether this type is in the process of being + /// defined. + bool isBeingDefined() const { return decl.getInt(); } + void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } + + static bool classof(const Type *T) { + 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 +/// to detect TagType objects of structs/unions/classes. +class RecordType : public TagType { +protected: + explicit RecordType(const RecordDecl *D) + : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { } + explicit RecordType(TypeClass TC, RecordDecl *D) + : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { } + friend class ASTContext; // ASTContext creates these. +public: + + RecordDecl *getDecl() const { + return reinterpret_cast<RecordDecl*>(TagType::getDecl()); + } + + // FIXME: This predicate is a helper to QualType/Type. It needs to + // recursively check all fields for const-ness. If any field is declared + // const, it needs to return false. + bool hasConstFields() const { return false; } + + // FIXME: RecordType needs to check when it is created that all fields are in + // the same address space, and return that. + unsigned getAddressSpace() const { return 0; } + + 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 RecordType *) { return true; } +}; + +/// EnumType - This is a helper class that allows the use of isa/cast/dyncast +/// to detect TagType objects of enums. +class EnumType : public TagType { + explicit EnumType(const EnumDecl *D) + : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { } + friend class ASTContext; // ASTContext creates these. +public: + + EnumDecl *getDecl() const { + return reinterpret_cast<EnumDecl*>(TagType::getDecl()); + } + + 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 EnumType *) { return true; } +}; + +class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { + unsigned Depth : 15; + unsigned Index : 16; + unsigned ParameterPack : 1; + IdentifierInfo *Name; + + TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, + QualType Canon) + : Type(TemplateTypeParm, Canon, /*Dependent=*/true), + Depth(D), Index(I), ParameterPack(PP), Name(N) { } + + TemplateTypeParmType(unsigned D, unsigned I, bool PP) + : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true), + Depth(D), Index(I), ParameterPack(PP), Name(0) { } + + friend class ASTContext; // ASTContext creates these + +public: + unsigned getDepth() const { return Depth; } + unsigned getIndex() const { return Index; } + bool isParameterPack() const { return ParameterPack; } + IdentifierInfo *getName() const { return Name; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Depth, Index, ParameterPack, Name); + } + + static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, + unsigned Index, bool ParameterPack, + IdentifierInfo *Name) { + ID.AddInteger(Depth); + ID.AddInteger(Index); + ID.AddBoolean(ParameterPack); + ID.AddPointer(Name); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == TemplateTypeParm; + } + static bool classof(const TemplateTypeParmType *T) { return true; } +}; + +/// \brief Represents the result of substituting a type for a template +/// type parameter. +/// +/// Within an instantiated template, all template type parameters have +/// been replaced with these. They are used solely to record that a +/// type was originally written as a template type parameter; +/// therefore they are never canonical. +class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { + // The original type parameter. + const TemplateTypeParmType *Replaced; + + SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) + : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()), + Replaced(Param) { } + + friend class ASTContext; + +public: + IdentifierInfo *getName() const { return Replaced->getName(); } + + /// Gets the template parameter that was substituted for. + const TemplateTypeParmType *getReplacedParameter() const { + return Replaced; + } + + /// Gets the type that was substituted for the template + /// parameter. + QualType getReplacementType() const { + return getCanonicalTypeInternal(); + } + + bool isSugared() const { return true; } + QualType desugar() const { return getReplacementType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getReplacedParameter(), getReplacementType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, + const TemplateTypeParmType *Replaced, + QualType Replacement) { + ID.AddPointer(Replaced); + ID.AddPointer(Replacement.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == SubstTemplateTypeParm; + } + static bool classof(const SubstTemplateTypeParmType *T) { return true; } +}; + +/// \brief Represents the type of a template specialization as written +/// in the source code. +/// +/// Template specialization types represent the syntactic form of a +/// template-id that refers to a type, e.g., @c vector<int>. Some +/// template specialization types are syntactic sugar, whose canonical +/// type will point to some other type node that represents the +/// instantiation or class template specialization. For example, a +/// class template specialization type of @c vector<int> will refer to +/// a tag type for the instantiation +/// @c std::vector<int, std::allocator<int>>. +/// +/// Other template specialization types, for which the template name +/// is dependent, may be canonical types. These types are always +/// dependent. +class TemplateSpecializationType + : public Type, public llvm::FoldingSetNode { + + // The ASTContext is currently needed in order to profile expressions. + // FIXME: avoid this. + // + // The bool is whether this is a current instantiation. + llvm::PointerIntPair<ASTContext*, 1, bool> ContextAndCurrentInstantiation; + + /// \brief The name of the template being specialized. + TemplateName Template; + + /// \brief - The number of template arguments named in this class + /// template specialization. + unsigned NumArgs; + + TemplateSpecializationType(ASTContext &Context, + TemplateName T, + bool IsCurrentInstantiation, + const TemplateArgument *Args, + unsigned NumArgs, QualType Canon); + + virtual void Destroy(ASTContext& C); + + friend class ASTContext; // ASTContext creates these + +public: + /// \brief Determine whether any of the given template arguments are + /// dependent. + static bool anyDependentTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs); + + static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, + unsigned NumArgs); + + static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &); + + /// \brief Print a template argument list, including the '<' and '>' + /// enclosing the template arguments. + static std::string PrintTemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs, + const PrintingPolicy &Policy); + + static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args, + unsigned NumArgs, + const PrintingPolicy &Policy); + + static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, + const PrintingPolicy &Policy); + + /// True if this template specialization type matches a current + /// instantiation in the context in which it is found. + bool isCurrentInstantiation() const { + return ContextAndCurrentInstantiation.getInt(); + } + + typedef const TemplateArgument * iterator; + + iterator begin() const { return getArgs(); } + iterator end() const; + + /// \brief Retrieve the name of the template that we are specializing. + TemplateName getTemplateName() const { return Template; } + + /// \brief Retrieve the template arguments. + const TemplateArgument *getArgs() const { + return reinterpret_cast<const TemplateArgument *>(this + 1); + } + + /// \brief Retrieve the number of template arguments. + unsigned getNumArgs() const { return NumArgs; } + + /// \brief Retrieve a specific template argument as a type. + /// \precondition @c isArgType(Arg) + const TemplateArgument &getArg(unsigned Idx) const; + + bool isSugared() const { + return !isDependentType() || isCurrentInstantiation(); + } + QualType desugar() const { return getCanonicalTypeInternal(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Template, isCurrentInstantiation(), getArgs(), NumArgs, + *ContextAndCurrentInstantiation.getPointer()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, + bool IsCurrentInstantiation, + const TemplateArgument *Args, + unsigned NumArgs, + ASTContext &Context); + + static bool classof(const Type *T) { + return T->getTypeClass() == TemplateSpecialization; + } + static bool classof(const TemplateSpecializationType *T) { return true; } +}; + +/// \brief The injected class name of a C++ class template or class +/// template partial specialization. Used to record that a type was +/// spelled with a bare identifier rather than as a template-id; the +/// equivalent for non-templated classes is just RecordType. +/// +/// Injected class name types are always dependent. Template +/// instantiation turns these into RecordTypes. +/// +/// Injected class name types are always canonical. This works +/// because it is impossible to compare an injected class name type +/// with the corresponding non-injected template type, for the same +/// reason that it is impossible to directly compare template +/// parameters from different dependent contexts: injected class name +/// types can only occur within the scope of a particular templated +/// declaration, and within that scope every template specialization +/// will canonicalize to the injected class name (when appropriate +/// according to the rules of the language). +class InjectedClassNameType : public Type { + CXXRecordDecl *Decl; + + /// The template specialization which this type represents. + /// For example, in + /// template <class T> class A { ... }; + /// this is A<T>, whereas in + /// template <class X, class Y> class A<B<X,Y> > { ... }; + /// this is A<B<X,Y> >. + /// + /// It is always unqualified, always a template specialization type, + /// and always dependent. + QualType InjectedType; + + friend class ASTContext; // ASTContext creates these. + friend class TagDecl; // TagDecl mutilates the Decl + InjectedClassNameType(CXXRecordDecl *D, QualType TST) + : Type(InjectedClassName, QualType(), true), + Decl(D), InjectedType(TST) { + assert(isa<TemplateSpecializationType>(TST)); + assert(!TST.hasQualifiers()); + assert(TST->isDependentType()); + } + +public: + QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { + return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); + } + + CXXRecordDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == InjectedClassName; + } + static bool classof(const InjectedClassNameType *T) { return true; } +}; + +/// \brief The kind of a tag type. +enum TagTypeKind { + /// \brief The "struct" keyword. + TTK_Struct, + /// \brief The "union" keyword. + TTK_Union, + /// \brief The "class" keyword. + TTK_Class, + /// \brief The "enum" keyword. + TTK_Enum +}; + +/// \brief The elaboration keyword that precedes a qualified type name or +/// introduces an elaborated-type-specifier. +enum ElaboratedTypeKeyword { + /// \brief The "struct" keyword introduces the elaborated-type-specifier. + ETK_Struct, + /// \brief The "union" keyword introduces the elaborated-type-specifier. + ETK_Union, + /// \brief The "class" keyword introduces the elaborated-type-specifier. + ETK_Class, + /// \brief The "enum" keyword introduces the elaborated-type-specifier. + ETK_Enum, + /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// \c typename T::type. + ETK_Typename, + /// \brief No keyword precedes the qualified type name. + ETK_None +}; + +/// A helper class for Type nodes having an ElaboratedTypeKeyword. +/// The keyword in stored in the free bits of the base class. +/// Also provides a few static helpers for converting and printing +/// elaborated type keyword and tag type kind enumerations. +class TypeWithKeyword : public Type { + /// Keyword - Encodes an ElaboratedTypeKeyword enumeration constant. + unsigned Keyword : 3; + +protected: + TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, + QualType Canonical, bool dependent) + : Type(tc, Canonical, dependent), Keyword(Keyword) {} + +public: + virtual ~TypeWithKeyword(); // pin vtable to Type.cpp + + ElaboratedTypeKeyword getKeyword() const { + return static_cast<ElaboratedTypeKeyword>(Keyword); + } + + /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into an elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec); + + /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into a tag type kind. It is an error to provide a type specifier + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec); + + /// getKeywordForTagDeclKind - Converts a TagTypeKind into an + /// elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag); + + /// getTagTypeKindForKeyword - Converts an elaborated type keyword into + // a TagTypeKind. It is an error to provide an elaborated type keyword + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword); + + static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); + + static const char *getKeywordName(ElaboratedTypeKeyword Keyword); + + static const char *getTagTypeKindName(TagTypeKind Kind) { + return getKeywordName(getKeywordForTagTypeKind(Kind)); + } + + class CannotCastToThisType {}; + static CannotCastToThisType classof(const Type *); +}; + +/// \brief Represents a type that was referred to using an elaborated type +/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, +/// or both. +/// +/// This type is used to keep track of a type name as written in the +/// source code, including tag keywords and any nested-name-specifiers. +/// The type itself is always "sugar", used to express what was written +/// in the source code but containing no additional semantic information. +class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { + + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + /// \brief The type that this qualified name refers to. + QualType NamedType; + + ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + QualType NamedType, QualType CanonType) + : TypeWithKeyword(Keyword, Elaborated, CanonType, + NamedType->isDependentType()), + NNS(NNS), NamedType(NamedType) { + assert(!(Keyword == ETK_None && NNS == 0) && + "ElaboratedType cannot have elaborated type keyword " + "and name qualifier both null."); + } + + friend class ASTContext; // ASTContext creates these + +public: + + /// \brief Retrieve the qualification on this type. + NestedNameSpecifier *getQualifier() const { return NNS; } + + /// \brief Retrieve the type named by the qualified-id. + QualType getNamedType() const { return NamedType; } + + /// \brief Remove a single level of sugar. + QualType desugar() const { return getNamedType(); } + + /// \brief Returns whether this type directly provides sugar. + bool isSugared() const { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getKeyword(), NNS, NamedType); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, QualType NamedType) { + ID.AddInteger(Keyword); + ID.AddPointer(NNS); + NamedType.Profile(ID); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == Elaborated; + } + static bool classof(const ElaboratedType *T) { return true; } +}; + +/// \brief Represents a qualified type name for which the type name is +/// 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 +/// 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 { + + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + typedef llvm::PointerUnion<const IdentifierInfo *, + const TemplateSpecializationType *> NameType; + + /// \brief The type that this typename specifier refers to. + NameType Name; + + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const IdentifierInfo *Name, QualType CanonType) + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Name) { + assert(NNS->isDependent() && + "DependentNameType requires a dependent nested-name-specifier"); + } + + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const TemplateSpecializationType *Ty, QualType CanonType) + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Ty) { + assert(NNS->isDependent() && + "DependentNameType requires a dependent nested-name-specifier"); + } + + friend class ASTContext; // ASTContext creates these + +public: + + /// \brief Retrieve the qualification on this type. + NestedNameSpecifier *getQualifier() const { return NNS; } + + /// \brief Retrieve the type named by the typename specifier as an + /// identifier. + /// + /// This routine will return a non-NULL identifier pointer when the + /// form of the original typename was terminated by an identifier, + /// e.g., "typename T::type". + const IdentifierInfo *getIdentifier() const { + return Name.dyn_cast<const IdentifierInfo *>(); + } + + /// \brief Retrieve the type named by the typename specifier as a + /// type specialization. + const TemplateSpecializationType *getTemplateId() const { + return Name.dyn_cast<const TemplateSpecializationType *>(); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getKeyword(), NNS, Name); + } + + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, NameType Name) { + ID.AddInteger(Keyword); + ID.AddPointer(NNS); + ID.AddPointer(Name.getOpaqueValue()); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentName; + } + static bool classof(const DependentNameType *T) { return true; } +}; + +/// ObjCObjectType - Represents a class type in Objective C. +/// Every Objective C type is a combination of a base type and a +/// list of protocols. +/// +/// Given the following declarations: +/// @class C; +/// @protocol P; +/// +/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType +/// with base C and no protocols. +/// +/// 'C<P>' is an ObjCObjectType with base C and protocol list [P]. +/// +/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose +/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType +/// and no protocols. +/// +/// 'id<P>' is an ObjCPointerType whose pointee is an ObjCObjecType +/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually +/// this should get its own sugar class to better represent the source. +class ObjCObjectType : public Type { + // Pad the bit count up so that NumProtocols is 2-byte aligned + unsigned : BitsRemainingInType - 16; + + /// \brief The number of protocols stored after the + /// ObjCObjectPointerType node. + /// + /// These protocols are those written directly on the type. If + /// protocol qualifiers ever become additive, the iterators will + /// get kindof complicated. + /// + /// In the canonical object type, these are sorted alphabetically + /// and uniqued. + unsigned NumProtocols : 16; + + /// Either a BuiltinType or an InterfaceType or sugar for either. + QualType BaseType; + + ObjCProtocolDecl * const *getProtocolStorage() const { + return const_cast<ObjCObjectType*>(this)->getProtocolStorage(); + } + + ObjCProtocolDecl **getProtocolStorage(); + +protected: + ObjCObjectType(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, unsigned NumProtocols); + + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(enum Nonce_ObjCInterface) + : Type(ObjCInterface, QualType(), false), + NumProtocols(0), + BaseType(QualType(this_(), 0)) {} + +protected: + Linkage getLinkageImpl() const; // key function + +public: + /// getBaseType - Gets the base type of this object type. This is + /// always (possibly sugar for) one of: + /// - the 'id' builtin type (as opposed to the 'id' type visible to the + /// user, which is a typedef for an ObjCPointerType) + /// - the 'Class' builtin type (same caveat) + /// - an ObjCObjectType (currently always an ObjCInterfaceType) + QualType getBaseType() const { return BaseType; } + + bool isObjCId() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); + } + bool isObjCClass() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); + } + bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } + bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } + bool isObjCUnqualifiedIdOrClass() const { + if (!qual_empty()) return false; + if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>()) + return T->getKind() == BuiltinType::ObjCId || + T->getKind() == BuiltinType::ObjCClass; + return false; + } + bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } + bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); } + + /// Gets the interface declaration for this object type, if the base type + /// really is an interface. + ObjCInterfaceDecl *getInterface() const; + + typedef ObjCProtocolDecl * const *qual_iterator; + + qual_iterator qual_begin() const { return getProtocolStorage(); } + qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } + + bool qual_empty() const { return getNumProtocols() == 0; } + + /// getNumProtocols - Return the number of qualifying protocols in this + /// interface type, or 0 if there are none. + unsigned getNumProtocols() const { return NumProtocols; } + + /// \brief Fetch a protocol by index. + ObjCProtocolDecl *getProtocol(unsigned I) const { + assert(I < getNumProtocols() && "Out-of-range protocol access"); + return qual_begin()[I]; + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObject || + T->getTypeClass() == ObjCInterface; + } + static bool classof(const ObjCObjectType *) { return true; } +}; + +/// ObjCObjectTypeImpl - A class providing a concrete implementation +/// of ObjCObjectType, so as to not increase the footprint of +/// ObjCInterfaceType. Code outside of ASTContext and the core type +/// system should not reference this type. +class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { + friend class ASTContext; + + // If anyone adds fields here, ObjCObjectType::getProtocolStorage() + // will need to be modified. + + ObjCObjectTypeImpl(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) + : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} + +public: + void Destroy(ASTContext& C); // key function + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, + QualType Base, + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); +}; + +inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { + return reinterpret_cast<ObjCProtocolDecl**>( + static_cast<ObjCObjectTypeImpl*>(this) + 1); +} + +/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for +/// object oriented design. They basically correspond to C++ classes. There +/// are two kinds of interface types, normal interfaces like "NSString" and +/// qualified interfaces, which are qualified with a protocol list like +/// "NSString<NSCopyable, NSAmazing>". +/// +/// ObjCInterfaceType guarantees the following properties when considered +/// as a subtype of its superclass, ObjCObjectType: +/// - There are no protocol qualifiers. To reinforce this, code which +/// tries to invoke the protocol methods via an ObjCInterfaceType will +/// fail to compile. +/// - It is its own base type. That is, if T is an ObjCInterfaceType*, +/// T->getBaseType() == QualType(T, 0). +class ObjCInterfaceType : public ObjCObjectType { + ObjCInterfaceDecl *Decl; + + ObjCInterfaceType(const ObjCInterfaceDecl *D) + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast<ObjCInterfaceDecl*>(D)) {} + friend class ASTContext; // ASTContext creates these. +public: + void Destroy(ASTContext& C); // key function + + /// getDecl - Get the declaration of this interface. + ObjCInterfaceDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCInterface; + } + static bool classof(const ObjCInterfaceType *) { return true; } + + // Nonsense to "hide" certain members of ObjCObjectType within this + // class. People asking for protocols on an ObjCInterfaceType are + // not going to get what they want: ObjCInterfaceTypes are + // guaranteed to have no protocols. + enum { + qual_iterator, + qual_begin, + qual_end, + getNumProtocols, + getProtocol + }; +}; + +inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { + if (const ObjCInterfaceType *T = + getBaseType()->getAs<ObjCInterfaceType>()) + return T->getDecl(); + return 0; +} + +/// ObjCObjectPointerType - Used to represent a pointer to an +/// Objective C object. These are constructed from pointer +/// declarators when the pointee type is an ObjCObjectType (or sugar +/// for one). In addition, the 'id' and 'Class' types are typedefs +/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>' +/// are translated into these. +/// +/// Pointers to pointers to Objective C objects are still PointerTypes; +/// only the first level of pointer gets it own type implementation. +class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; + + ObjCObjectPointerType(QualType Canonical, QualType Pointee) + : Type(ObjCObjectPointer, Canonical, false), + PointeeType(Pointee) {} + friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + +public: + void Destroy(ASTContext& C); + + /// getPointeeType - Gets the type pointed to by this ObjC pointer. + /// The result will always be an ObjCObjectType or sugar thereof. + QualType getPointeeType() const { return PointeeType; } + + /// getObjCObjectType - Gets the type pointed to by this ObjC + /// pointer. This method always returns non-null. + /// + /// This method is equivalent to getPointeeType() except that + /// it discards any typedefs (or other sugar) between this + /// type and the "outermost" object type. So for: + /// @class A; @protocol P; @protocol Q; + /// typedef A<P> AP; + /// typedef A A1; + /// typedef A1<P> A1P; + /// typedef A1P<Q> A1PQ; + /// For 'A*', getObjectType() will return 'A'. + /// For 'A<P>*', getObjectType() will return 'A<P>'. + /// For 'AP*', getObjectType() will return 'A<P>'. + /// For 'A1*', getObjectType() will return 'A'. + /// For 'A1<P>*', getObjectType() will return 'A1<P>'. + /// For 'A1P*', getObjectType() will return 'A1<P>'. + /// For 'A1PQ*', getObjectType() will return 'A1<Q>', because + /// adding protocols to a protocol-qualified base discards the + /// old qualifiers (for now). But if it didn't, getObjectType() + /// would return 'A1P<Q>' (and we'd have to make iterating over + /// qualifiers more complicated). + const ObjCObjectType *getObjectType() const { + return PointeeType->getAs<ObjCObjectType>(); + } + + /// getInterfaceType - If this pointer points to an Objective C + /// @interface type, gets the type for that interface. Any protocol + /// qualifiers on the interface are ignored. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' + const ObjCInterfaceType *getInterfaceType() const { + return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>(); + } + + /// getInterfaceDecl - If this pointer points to an Objective @interface + /// type, gets the declaration for that interface. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' + ObjCInterfaceDecl *getInterfaceDecl() const { + return getObjectType()->getInterface(); + } + + /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if + /// its object type is the primitive 'id' type with no protocols. + bool isObjCIdType() const { + return getObjectType()->isObjCUnqualifiedId(); + } + + /// isObjCClassType - True if this is equivalent to the 'Class' type, + /// i.e. if its object tive is the primitive 'Class' type with no protocols. + 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 { + return getObjectType()->isObjCQualifiedId(); + } + + /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for + /// some non-empty set of protocols. + bool isObjCQualifiedClassType() const { + return getObjectType()->isObjCQualifiedClass(); + } + + /// An iterator over the qualifiers on the object type. Provided + /// for convenience. This will always iterate over the full set of + /// protocols on a type, not just those provided directly. + typedef ObjCObjectType::qual_iterator qual_iterator; + + qual_iterator qual_begin() const { + return getObjectType()->qual_begin(); + } + qual_iterator qual_end() const { + return getObjectType()->qual_end(); + } + bool qual_empty() const { return getObjectType()->qual_empty(); } + + /// getNumProtocols - Return the number of qualifying protocols on + /// the object type. + unsigned getNumProtocols() const { + return getObjectType()->getNumProtocols(); + } + + /// \brief Retrieve a qualifying protocol by index on the object + /// type. + ObjCProtocolDecl *getProtocol(unsigned I) const { + return getObjectType()->getProtocol(I); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + ID.AddPointer(T.getAsOpaquePtr()); + } + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObjectPointer; + } + static bool classof(const ObjCObjectPointerType *) { return true; } +}; + +/// A qualifier set is used to build a set of qualifiers. +class QualifierCollector : public Qualifiers { + ASTContext *Context; + +public: + QualifierCollector(Qualifiers Qs = Qualifiers()) + : Qualifiers(Qs), Context(0) {} + QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers()) + : Qualifiers(Qs), Context(&Context) {} + + void setContext(ASTContext &C) { Context = &C; } + + /// Collect any qualifiers on the given type and return an + /// unqualified type. + const Type *strip(QualType QT) { + addFastQualifiers(QT.getLocalFastQualifiers()); + if (QT.hasLocalNonFastQualifiers()) { + const ExtQuals *EQ = QT.getExtQualsUnsafe(); + Context = &EQ->getContext(); + addQualifiers(EQ->getQualifiers()); + return EQ->getBaseType(); + } + return QT.getTypePtrUnsafe(); + } + + /// Apply the collected qualifiers to the given type. + QualType apply(QualType QT) const; + + /// Apply the collected qualifiers to the given type. + QualType apply(const Type* T) const; + +}; + + +// Inline function definitions. + +inline bool QualType::isCanonical() const { + const Type *T = getTypePtr(); + if (hasLocalQualifiers()) + return T->isCanonicalUnqualified() && !isa<ArrayType>(T); + return T->isCanonicalUnqualified(); +} + +inline bool QualType::isCanonicalAsParam() const { + if (hasLocalQualifiers()) return false; + const Type *T = getTypePtr(); + return T->isCanonicalUnqualified() && + !isa<FunctionType>(T) && !isa<ArrayType>(T); +} + +inline bool QualType::isConstQualified() const { + return isLocalConstQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified(); +} + +inline bool QualType::isRestrictQualified() const { + return isLocalRestrictQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified(); +} + + +inline bool QualType::isVolatileQualified() const { + return isLocalVolatileQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified(); +} + +inline bool QualType::hasQualifiers() const { + return hasLocalQualifiers() || + getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers(); +} + +inline Qualifiers QualType::getQualifiers() const { + Qualifiers Quals = getLocalQualifiers(); + Quals.addQualifiers( + getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers()); + return Quals; +} + +inline unsigned QualType::getCVRQualifiers() const { + return getLocalCVRQualifiers() | + getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); +} + +/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this +/// type, returns them. Otherwise, if this is an array type, recurses +/// on the element type until some qualifiers have been found or a non-array +/// type reached. +inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const { + if (unsigned Quals = getCVRQualifiers()) + return Quals; + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getCVRQualifiersThroughArrayTypes(); + return 0; +} + +inline void QualType::removeConst() { + removeFastQualifiers(Qualifiers::Const); +} + +inline void QualType::removeRestrict() { + removeFastQualifiers(Qualifiers::Restrict); +} + +inline void QualType::removeVolatile() { + QualifierCollector Qc; + const Type *Ty = Qc.strip(*this); + if (Qc.hasVolatile()) { + Qc.removeVolatile(); + *this = Qc.apply(Ty); + } +} + +inline void QualType::removeCVRQualifiers(unsigned Mask) { + assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); + + // Fast path: we don't need to touch the slow qualifiers. + if (!(Mask & ~Qualifiers::FastMask)) { + removeFastQualifiers(Mask); + return; + } + + QualifierCollector Qc; + const Type *Ty = Qc.strip(*this); + Qc.removeCVRQualifiers(Mask); + *this = Qc.apply(Ty); +} + +/// getAddressSpace - Return the address space of this type. +inline unsigned QualType::getAddressSpace() const { + if (hasLocalNonFastQualifiers()) { + const ExtQuals *EQ = getExtQualsUnsafe(); + if (EQ->hasAddressSpace()) + return EQ->getAddressSpace(); + } + + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (CT.hasLocalNonFastQualifiers()) { + const ExtQuals *EQ = CT.getExtQualsUnsafe(); + if (EQ->hasAddressSpace()) + return EQ->getAddressSpace(); + } + + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getAddressSpace(); + if (const RecordType *RT = dyn_cast<RecordType>(CT)) + return RT->getAddressSpace(); + return 0; +} + +/// getObjCGCAttr - Return the gc attribute of this type. +inline Qualifiers::GC QualType::getObjCGCAttr() const { + if (hasLocalNonFastQualifiers()) { + const ExtQuals *EQ = getExtQualsUnsafe(); + if (EQ->hasObjCGCAttr()) + return EQ->getObjCGCAttr(); + } + + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (CT.hasLocalNonFastQualifiers()) { + const ExtQuals *EQ = CT.getExtQualsUnsafe(); + if (EQ->hasObjCGCAttr()) + return EQ->getObjCGCAttr(); + } + + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getObjCGCAttr(); + if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>()) + return PT->getPointeeType().getObjCGCAttr(); + // We most look at all pointer types, not just pointer to interface types. + if (const PointerType *PT = CT->getAs<PointerType>()) + return PT->getPointeeType().getObjCGCAttr(); + return Qualifiers::GCNone; +} + +inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { + if (const PointerType *PT = t.getAs<PointerType>()) { + if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) + return FT->getExtInfo(); + } else if (const FunctionType *FT = t.getAs<FunctionType>()) + return FT->getExtInfo(); + + return FunctionType::ExtInfo(); +} + +inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { + return getFunctionExtInfo(*t); +} + +/// isMoreQualifiedThan - Determine whether this type is more +/// qualified than the Other type. For example, "const volatile int" +/// is more qualified than "const int", "volatile int", and +/// "int". However, it is not more qualified than "const volatile +/// int". +inline bool QualType::isMoreQualifiedThan(QualType Other) const { + // FIXME: work on arbitrary qualifiers + unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); + unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); + if (getAddressSpace() != Other.getAddressSpace()) + return false; + return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals; +} + +/// isAtLeastAsQualifiedAs - Determine whether this type is at last +/// as qualified as the Other type. For example, "const volatile +/// int" is at least as qualified as "const int", "volatile int", +/// "int", and "const volatile int". +inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const { + // FIXME: work on arbitrary qualifiers + unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); + unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); + if (getAddressSpace() != Other.getAddressSpace()) + return false; + return (MyQuals | OtherQuals) == MyQuals; +} + +/// getNonReferenceType - If Type is a reference type (e.g., const +/// int&), returns the type that the reference refers to ("const +/// int"). Otherwise, returns the type itself. This routine is used +/// throughout Sema to implement C++ 5p6: +/// +/// If an expression initially has the type "reference to T" (8.3.2, +/// 8.5.3), the type is adjusted to "T" prior to any further +/// analysis, the expression designates the object or function +/// denoted by the reference, and the expression is an lvalue. +inline QualType QualType::getNonReferenceType() const { + if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>()) + return RefType->getPointeeType(); + else + return *this; +} + +inline bool Type::isFunctionType() const { + return isa<FunctionType>(CanonicalType); +} +inline bool Type::isPointerType() const { + return isa<PointerType>(CanonicalType); +} +inline bool Type::isAnyPointerType() const { + return isPointerType() || isObjCObjectPointerType(); +} +inline bool Type::isBlockPointerType() const { + return isa<BlockPointerType>(CanonicalType); +} +inline bool Type::isReferenceType() const { + return isa<ReferenceType>(CanonicalType); +} +inline bool Type::isLValueReferenceType() const { + return isa<LValueReferenceType>(CanonicalType); +} +inline bool Type::isRValueReferenceType() const { + return isa<RValueReferenceType>(CanonicalType); +} +inline bool Type::isFunctionPointerType() const { + if (const PointerType* T = getAs<PointerType>()) + return T->getPointeeType()->isFunctionType(); + else + return false; +} +inline bool Type::isMemberPointerType() const { + return isa<MemberPointerType>(CanonicalType); +} +inline bool Type::isMemberFunctionPointerType() const { + if (const MemberPointerType* T = getAs<MemberPointerType>()) + return T->getPointeeType()->isFunctionType(); + else + return false; +} +inline bool Type::isArrayType() const { + return isa<ArrayType>(CanonicalType); +} +inline bool Type::isConstantArrayType() const { + return isa<ConstantArrayType>(CanonicalType); +} +inline bool Type::isIncompleteArrayType() const { + return isa<IncompleteArrayType>(CanonicalType); +} +inline bool Type::isVariableArrayType() const { + return isa<VariableArrayType>(CanonicalType); +} +inline bool Type::isDependentSizedArrayType() const { + return isa<DependentSizedArrayType>(CanonicalType); +} +inline bool Type::isRecordType() const { + return isa<RecordType>(CanonicalType); +} +inline bool Type::isAnyComplexType() const { + return isa<ComplexType>(CanonicalType); +} +inline bool Type::isVectorType() const { + return isa<VectorType>(CanonicalType); +} +inline bool Type::isExtVectorType() const { + return isa<ExtVectorType>(CanonicalType); +} +inline bool Type::isObjCObjectPointerType() const { + return isa<ObjCObjectPointerType>(CanonicalType); +} +inline bool Type::isObjCObjectType() const { + return isa<ObjCObjectType>(CanonicalType); +} +inline bool Type::isObjCQualifiedIdType() const { + if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + return OPT->isObjCQualifiedIdType(); + return false; +} +inline bool Type::isObjCQualifiedClassType() const { + if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + return OPT->isObjCQualifiedClassType(); + return false; +} +inline bool Type::isObjCIdType() const { + if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + return OPT->isObjCIdType(); + return false; +} +inline bool Type::isObjCClassType() const { + if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + return OPT->isObjCClassType(); + return false; +} +inline bool Type::isObjCSelType() const { + if (const PointerType *OPT = getAs<PointerType>()) + return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); + return false; +} +inline bool Type::isObjCBuiltinType() const { + return isObjCIdType() || isObjCClassType() || isObjCSelType(); +} +inline bool Type::isTemplateTypeParmType() const { + return isa<TemplateTypeParmType>(CanonicalType); +} + +inline bool Type::isSpecificBuiltinType(unsigned K) const { + if (const BuiltinType *BT = getAs<BuiltinType>()) + if (BT->getKind() == (BuiltinType::Kind) K) + return true; + return false; +} + +/// \brief Determines whether this is a type for which one can define +/// an overloaded operator. +inline bool Type::isOverloadableType() const { + return isDependentType() || isRecordType() || isEnumeralType(); +} + +inline bool Type::hasPointerRepresentation() const { + return (isPointerType() || isReferenceType() || isBlockPointerType() || + isObjCObjectPointerType() || isNullPtrType()); +} + +inline bool Type::hasObjCPointerRepresentation() const { + return isObjCObjectPointerType(); +} + +/// Insertion operator for diagnostics. This allows sending QualType's into a +/// diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + QualType T) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), + Diagnostic::ak_qualtype); + return DB; +} + +/// Insertion operator for partial diagnostics. This allows sending QualType's +/// into a diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + QualType T) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), + Diagnostic::ak_qualtype); + return PD; +} + +// Helper class template that is used by Type::getAs to ensure that one does +// not try to look through a qualified type to get to an array type. +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; + + // If the canonical form of this type isn't the right kind, reject it. + if (!isa<T>(CanonicalType)) + return 0; + + // If this is a typedef for the type, strip the typedef off without + // losing all typedef information. + return cast<T>(getUnqualifiedDesugaredType()); +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h new file mode 100644 index 0000000..f988f0e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h @@ -0,0 +1,1308 @@ +//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- 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 TypeLoc interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPELOC_H +#define LLVM_CLANG_AST_TYPELOC_H + +#include "clang/AST/Type.h" +#include "clang/AST/Decl.h" +#include "clang/AST/TemplateBase.h" +#include "clang/Basic/Specifiers.h" + +namespace clang { + class ParmVarDecl; + class TypeSourceInfo; + class UnqualTypeLoc; + +// Predeclare all the type nodes. +#define ABSTRACT_TYPELOC(Class, Base) +#define TYPELOC(Class, Base) \ + class Class##TypeLoc; +#include "clang/AST/TypeLocNodes.def" + +/// \brief Base wrapper for a particular "section" of type source info. +/// +/// A client should use the TypeLoc subclasses through cast/dyn_cast in order to +/// get at the actual information. +class TypeLoc { +protected: + // The correctness of this relies on the property that, for Type *Ty, + // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty + void *Ty; + void *Data; + +public: + /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, + /// except it also defines a Qualified enum that corresponds to the + /// QualifiedLoc class. + enum TypeLocClass { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + Class = Type::Class, +#include "clang/AST/TypeNodes.def" + Qualified + }; + + TypeLoc() : Ty(0), Data(0) { } + TypeLoc(QualType ty, void *opaqueData) + : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } + TypeLoc(Type *ty, void *opaqueData) + : Ty(ty), Data(opaqueData) { } + + TypeLocClass getTypeLocClass() const { + if (getType().hasLocalQualifiers()) return Qualified; + return (TypeLocClass) getType()->getTypeClass(); + } + + bool isNull() const { return !Ty; } + operator bool() const { return Ty; } + + /// \brief Returns the size of type source info data block for the given type. + static unsigned getFullDataSizeForType(QualType Ty); + + /// \brief Get the type for which this source info wrapper provides + /// information. + QualType getType() const { + return QualType::getFromOpaquePtr(Ty); + } + + Type *getTypePtr() const { + return QualType::getFromOpaquePtr(Ty).getTypePtr(); + } + + /// \brief Get the pointer where source information is stored. + void *getOpaqueData() const { + return Data; + } + + /// \brief Get the begin source location. + SourceLocation getBeginLoc() const; + + /// \brief Get the end source location. + SourceLocation getEndLoc() const; + + /// \brief Get the full source range. + SourceRange getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); + } + + /// \brief Get the local source range. + SourceRange getLocalSourceRange() const { + return getLocalSourceRangeImpl(*this); + } + + /// \brief Returns the size of the type source info data block. + unsigned getFullDataSize() const { + return getFullDataSizeForType(getType()); + } + + /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the + /// TypeLoc is a PointerLoc and next TypeLoc is for "int". + TypeLoc getNextTypeLoc() const { + return getNextTypeLocImpl(*this); + } + + /// \brief Skips past any qualifiers, if this is qualified. + UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header + + /// \brief Initializes this to state that every location in this + /// type is the given location. + /// + /// This method exists to provide a simple transition for code that + /// relies on location-less types. + void initialize(SourceLocation Loc) const { + initializeImpl(*this, Loc); + } + + friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { + return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; + } + + friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) { + return !(LHS == RHS); + } + + static bool classof(const TypeLoc *TL) { return true; } + +private: + static void initializeImpl(TypeLoc TL, SourceLocation Loc); + static TypeLoc getNextTypeLocImpl(TypeLoc TL); + static SourceRange getLocalSourceRangeImpl(TypeLoc TL); +}; + +/// \brief Return the TypeLoc for a type source info. +inline TypeLoc TypeSourceInfo::getTypeLoc() const { + return TypeLoc(Ty, (void*)(this + 1)); +} + +/// \brief Wrapper of type source information for a type with +/// no direct quqlaifiers. +class UnqualTypeLoc : public TypeLoc { +public: + UnqualTypeLoc() {} + UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {} + + Type *getTypePtr() const { + return reinterpret_cast<Type*>(Ty); + } + + TypeLocClass getTypeLocClass() const { + return (TypeLocClass) getTypePtr()->getTypeClass(); + } + + static bool classof(const TypeLoc *TL) { + return !TL->getType().hasLocalQualifiers(); + } + static bool classof(const UnqualTypeLoc *TL) { return true; } +}; + +/// \brief Wrapper of type source information for a type with +/// non-trivial direct qualifiers. +/// +/// Currently, we intentionally do not provide source location for +/// type qualifiers. +class QualifiedTypeLoc : public TypeLoc { +public: + SourceRange getLocalSourceRange() const { + return SourceRange(); + } + + UnqualTypeLoc getUnqualifiedLoc() const { + return UnqualTypeLoc(getTypePtr(), Data); + } + + /// Initializes the local data of this type source info block to + /// provide no information. + void initializeLocal(SourceLocation Loc) { + // do nothing + } + + TypeLoc getNextTypeLoc() const { + return getUnqualifiedLoc(); + } + + /// \brief Returns the size of the type source info data block that is + /// specific to this type. + unsigned getLocalDataSize() const { + // In fact, we don't currently preserve any location information + // for qualifiers. + return 0; + } + + /// \brief Returns the size of the type source info data block. + unsigned getFullDataSize() const { + return getLocalDataSize() + + getFullDataSizeForType(getType().getLocalUnqualifiedType()); + } + + static bool classof(const TypeLoc *TL) { + return TL->getType().hasLocalQualifiers(); + } + static bool classof(const QualifiedTypeLoc *TL) { return true; } +}; + +inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { + if (isa<QualifiedTypeLoc>(this)) + return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc(); + return cast<UnqualTypeLoc>(*this); +} + +/// A metaprogramming base class for TypeLoc classes which correspond +/// to a particular Type subclass. It is accepted for a single +/// TypeLoc class to correspond to multiple Type classes. +/// +/// \param Base a class from which to derive +/// \param Derived the class deriving from this one +/// \param TypeClass the concrete Type subclass associated with this +/// location type +/// \param LocalData the structure type of local location data for +/// this type +/// +/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or +/// else the world will end. +/// +/// TypeLocs with non-constant amounts of local data should override +/// getExtraLocalDataSize(); getExtraLocalData() will then point to +/// this extra memory. +/// +/// TypeLocs with an inner type should define +/// QualType getInnerType() const +/// and getInnerTypeLoc() will then point to this inner type's +/// location data. +/// +/// A word about hierarchies: this template is not designed to be +/// derived from multiple times in a hierarchy. It is also not +/// designed to be used for classes where subtypes might provide +/// different amounts of source information. It should be subclassed +/// only at the deepest portion of the hierarchy where all children +/// have identical source information; if that's an abstract type, +/// then further descendents should inherit from +/// InheritingConcreteTypeLoc instead. +template <class Base, class Derived, class TypeClass, class LocalData> +class ConcreteTypeLoc : public Base { + + const Derived *asDerived() const { + return static_cast<const Derived*>(this); + } + +public: + unsigned getLocalDataSize() const { + return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); + } + // Give a default implementation that's useful for leaf types. + unsigned getFullDataSize() const { + return asDerived()->getLocalDataSize() + getInnerTypeSize(); + } + + static bool classofType(const Type *Ty) { + return TypeClass::classof(Ty); + } + + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const Derived *TL) { + return true; + } + + TypeLoc getNextTypeLoc() const { + return getNextTypeLoc(asDerived()->getInnerType()); + } + + TypeClass *getTypePtr() const { + return cast<TypeClass>(Base::getTypePtr()); + } + +protected: + unsigned getExtraLocalDataSize() const { + return 0; + } + + LocalData *getLocalData() const { + return static_cast<LocalData*>(Base::Data); + } + + /// Gets a pointer past the Info structure; useful for classes with + /// local data that can't be captured in the Info (e.g. because it's + /// of variable size). + void *getExtraLocalData() const { + return getLocalData() + 1; + } + + void *getNonLocalData() const { + return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize(); + } + + struct HasNoInnerType {}; + HasNoInnerType getInnerType() const { return HasNoInnerType(); } + + TypeLoc getInnerTypeLoc() const { + return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); + } + +private: + unsigned getInnerTypeSize() const { + return getInnerTypeSize(asDerived()->getInnerType()); + } + + unsigned getInnerTypeSize(HasNoInnerType _) const { + return 0; + } + + unsigned getInnerTypeSize(QualType _) const { + return getInnerTypeLoc().getFullDataSize(); + } + + TypeLoc getNextTypeLoc(HasNoInnerType _) const { + return TypeLoc(); + } + + TypeLoc getNextTypeLoc(QualType T) const { + return TypeLoc(T, getNonLocalData()); + } +}; + +/// A metaprogramming class designed for concrete subtypes of abstract +/// types where all subtypes share equivalently-structured source +/// information. See the note on ConcreteTypeLoc. +template <class Base, class Derived, class TypeClass> +class InheritingConcreteTypeLoc : public Base { +public: + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const Derived *TL) { + return true; + } + + TypeClass *getTypePtr() const { + return cast<TypeClass>(Base::getTypePtr()); + } +}; + + +struct TypeSpecLocInfo { + SourceLocation NameLoc; +}; + +/// \brief A reasonable base class for TypeLocs that correspond to +/// types that are written as a type-specifier. +class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + TypeSpecTypeLoc, + Type, + TypeSpecLocInfo> { +public: + enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + SourceRange getLocalSourceRange() const { + return SourceRange(getNameLoc(), getNameLoc()); + } + void initializeLocal(SourceLocation Loc) { + setNameLoc(Loc); + } + + static bool classof(const TypeLoc *TL); + static bool classof(const TypeSpecTypeLoc *TL) { return true; } +}; + + +struct BuiltinLocInfo { + SourceLocation BuiltinLoc; +}; + +/// \brief Wrapper for source info for builtin types. +class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + BuiltinTypeLoc, + BuiltinType, + BuiltinLocInfo> { +public: + enum { LocalDataSize = sizeof(BuiltinLocInfo) }; + + SourceLocation getBuiltinLoc() const { + return getLocalData()->BuiltinLoc; + } + void setBuiltinLoc(SourceLocation Loc) { + getLocalData()->BuiltinLoc = Loc; + } + + SourceLocation getNameLoc() const { return getBuiltinLoc(); } + + WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { + return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); + } + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { + return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); + } + + bool needsExtraLocalData() const { + BuiltinType::Kind bk = getTypePtr()->getKind(); + return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) + || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) + || bk == BuiltinType::UChar + || bk == BuiltinType::SChar; + } + + unsigned getExtraLocalDataSize() const { + return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getBuiltinLoc(), getBuiltinLoc()); + } + + TypeSpecifierSign getWrittenSignSpec() const { + if (needsExtraLocalData()) + return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign); + else + return TSS_unspecified; + } + bool hasWrittenSignSpec() const { + return getWrittenSignSpec() != TSS_unspecified; + } + void setWrittenSignSpec(TypeSpecifierSign written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Sign = written; + } + + TypeSpecifierWidth getWrittenWidthSpec() const { + if (needsExtraLocalData()) + return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width); + else + return TSW_unspecified; + } + bool hasWrittenWidthSpec() const { + return getWrittenWidthSpec() != TSW_unspecified; + } + void setWrittenWidthSpec(TypeSpecifierWidth written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Width = written; + } + + TypeSpecifierType getWrittenTypeSpec() const; + bool hasWrittenTypeSpec() const { + return getWrittenTypeSpec() != TST_unspecified; + } + void setWrittenTypeSpec(TypeSpecifierType written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().Type = written; + } + + bool hasModeAttr() const { + if (needsExtraLocalData()) + return getWrittenBuiltinSpecs().ModeAttr; + else + return false; + } + void setModeAttr(bool written) { + if (needsExtraLocalData()) + getWrittenBuiltinSpecs().ModeAttr = written; + } + + void initializeLocal(SourceLocation Loc) { + setBuiltinLoc(Loc); + if (needsExtraLocalData()) { + WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); + wbs.Sign = TSS_unspecified; + wbs.Width = TSW_unspecified; + wbs.Type = TST_unspecified; + wbs.ModeAttr = false; + } + } +}; + + +/// \brief Wrapper for source info for typedefs. +class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypedefTypeLoc, + TypedefType> { +public: + TypedefDecl *getTypedefDecl() const { + return getTypePtr()->getDecl(); + } +}; + +/// \brief Wrapper for source info for injected class names of class +/// templates. +class InjectedClassNameTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + InjectedClassNameTypeLoc, + InjectedClassNameType> { +}; + +/// \brief Wrapper for source info for unresolved typename using decls. +class UnresolvedUsingTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + UnresolvedUsingTypeLoc, + UnresolvedUsingType> { +public: + UnresolvedUsingTypenameDecl *getDecl() const { + return getTypePtr()->getDecl(); + } +}; + +/// \brief Wrapper for source info for tag types. Note that this only +/// records source info for the name itself; a type written 'struct foo' +/// should be represented as an ElaboratedTypeLoc. We currently +/// only do that when C++ is enabled because of the expense of +/// creating an ElaboratedType node for so many type references in C. +class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TagTypeLoc, + TagType> { +public: + TagDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for record types. +class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + RecordTypeLoc, + RecordType> { +public: + RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for enum types. +class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + EnumTypeLoc, + EnumType> { +public: + EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for template type parameters. +class TemplateTypeParmTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TemplateTypeParmTypeLoc, + TemplateTypeParmType> { +}; + +/// \brief Wrapper for substituted template type parameters. +class SubstTemplateTypeParmTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + SubstTemplateTypeParmTypeLoc, + SubstTemplateTypeParmType> { +}; + + +struct ObjCProtocolListLocInfo { + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; + bool HasBaseTypeAsWritten; +}; + +// A helper class for defining ObjC TypeLocs that can qualified with +// protocols. +// +// TypeClass basically has to be either ObjCInterfaceType or +// ObjCObjectPointerType. +class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCObjectTypeLoc, + ObjCObjectType, + ObjCProtocolListLocInfo> { + // SourceLocations are stored after Info, one for each Protocol. + SourceLocation *getProtocolLocArray() const { + return (SourceLocation*) this->getExtraLocalData(); + } + +public: + SourceLocation getLAngleLoc() const { + return this->getLocalData()->LAngleLoc; + } + void setLAngleLoc(SourceLocation Loc) { + this->getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return this->getLocalData()->RAngleLoc; + } + void setRAngleLoc(SourceLocation Loc) { + this->getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumProtocols() const { + return this->getTypePtr()->getNumProtocols(); + } + + SourceLocation getProtocolLoc(unsigned i) const { + assert(i < getNumProtocols() && "Index is out of bounds!"); + return getProtocolLocArray()[i]; + } + void setProtocolLoc(unsigned i, SourceLocation Loc) { + assert(i < getNumProtocols() && "Index is out of bounds!"); + getProtocolLocArray()[i] = Loc; + } + + ObjCProtocolDecl *getProtocol(unsigned i) const { + assert(i < getNumProtocols() && "Index is out of bounds!"); + return *(this->getTypePtr()->qual_begin() + i); + } + + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseTypeAsWritten; + } + + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseTypeAsWritten = HasBaseType; + } + + TypeLoc getBaseLoc() const { + return getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getLAngleLoc(), getRAngleLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setHasBaseTypeAsWritten(true); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); + } + + unsigned getExtraLocalDataSize() const { + return this->getNumProtocols() * sizeof(SourceLocation); + } + + QualType getInnerType() const { + return getTypePtr()->getBaseType(); + } +}; + + +struct ObjCInterfaceLocInfo { + SourceLocation NameLoc; +}; + +/// \brief Wrapper for source info for ObjC interfaces. +class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCInterfaceTypeLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { +public: + ObjCInterfaceDecl *getIFaceDecl() const { + return getTypePtr()->getDecl(); + } + + SourceLocation getNameLoc() const { + return getLocalData()->NameLoc; + } + + void setNameLoc(SourceLocation Loc) { + getLocalData()->NameLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getNameLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setNameLoc(Loc); + } +}; + + +struct PointerLikeLocInfo { + SourceLocation StarLoc; +}; + +/// A base class for +template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> +class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, + TypeClass, LocalData> { +public: + SourceLocation getSigilLoc() const { + return this->getLocalData()->StarLoc; + } + void setSigilLoc(SourceLocation Loc) { + this->getLocalData()->StarLoc = Loc; + } + + TypeLoc getPointeeLoc() const { + return this->getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getSigilLoc(), getSigilLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setSigilLoc(Loc); + } + + QualType getInnerType() const { + return this->getTypePtr()->getPointeeType(); + } +}; + + +/// \brief Wrapper for source info for pointers. +class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, + PointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + + +/// \brief Wrapper for source info for block pointers. +class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, + BlockPointerType> { +public: + SourceLocation getCaretLoc() const { + return getSigilLoc(); + } + void setCaretLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + + +/// \brief Wrapper for source info for member pointers. +class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, + MemberPointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + +/// Wraps an ObjCPointerType with source location information. +class ObjCObjectPointerTypeLoc : + public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, + ObjCObjectPointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + + +class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, + ReferenceType> { +public: + QualType getInnerType() const { + return getTypePtr()->getPointeeTypeAsWritten(); + } +}; + +class LValueReferenceTypeLoc : + public InheritingConcreteTypeLoc<ReferenceTypeLoc, + LValueReferenceTypeLoc, + LValueReferenceType> { +public: + SourceLocation getAmpLoc() const { + return getSigilLoc(); + } + void setAmpLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + +class RValueReferenceTypeLoc : + public InheritingConcreteTypeLoc<ReferenceTypeLoc, + RValueReferenceTypeLoc, + RValueReferenceType> { +public: + SourceLocation getAmpAmpLoc() const { + return getSigilLoc(); + } + void setAmpAmpLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + + +struct FunctionLocInfo { + SourceLocation LParenLoc, RParenLoc; +}; + +/// \brief Wrapper for source info for functions. +class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + FunctionTypeLoc, + FunctionType, + FunctionLocInfo> { + // ParmVarDecls* are stored after Info, one for each argument. + ParmVarDecl **getParmArray() const { + return (ParmVarDecl**) getExtraLocalData(); + } + +public: + SourceLocation getLParenLoc() const { + return getLocalData()->LParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + getLocalData()->LParenLoc = Loc; + } + + SourceLocation getRParenLoc() const { + return getLocalData()->RParenLoc; + } + void setRParenLoc(SourceLocation Loc) { + getLocalData()->RParenLoc = Loc; + } + + unsigned getNumArgs() const { + if (isa<FunctionNoProtoType>(getTypePtr())) + return 0; + return cast<FunctionProtoType>(getTypePtr())->getNumArgs(); + } + ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } + void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } + + TypeLoc getResultLoc() const { + return getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setLParenLoc(Loc); + setRParenLoc(Loc); + for (unsigned i = 0, e = getNumArgs(); i != e; ++i) + setArg(i, NULL); + } + + /// \brief Returns the size of the type source info data block that is + /// specific to this type. + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(ParmVarDecl*); + } + + QualType getInnerType() const { return getTypePtr()->getResultType(); } +}; + +class FunctionProtoTypeLoc : + public InheritingConcreteTypeLoc<FunctionTypeLoc, + FunctionProtoTypeLoc, + FunctionProtoType> { +}; + +class FunctionNoProtoTypeLoc : + public InheritingConcreteTypeLoc<FunctionTypeLoc, + FunctionNoProtoTypeLoc, + FunctionNoProtoType> { +}; + + +struct ArrayLocInfo { + SourceLocation LBracketLoc, RBracketLoc; + Expr *Size; +}; + +/// \brief Wrapper for source info for arrays. +class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ArrayTypeLoc, + ArrayType, + ArrayLocInfo> { +public: + SourceLocation getLBracketLoc() const { + return getLocalData()->LBracketLoc; + } + void setLBracketLoc(SourceLocation Loc) { + getLocalData()->LBracketLoc = Loc; + } + + SourceLocation getRBracketLoc() const { + return getLocalData()->RBracketLoc; + } + void setRBracketLoc(SourceLocation Loc) { + getLocalData()->RBracketLoc = Loc; + } + + SourceRange getBracketsRange() const { + return SourceRange(getLBracketLoc(), getRBracketLoc()); + } + + Expr *getSizeExpr() const { + return getLocalData()->Size; + } + void setSizeExpr(Expr *Size) { + getLocalData()->Size = Size; + } + + TypeLoc getElementLoc() const { + return getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getLBracketLoc(), getRBracketLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setLBracketLoc(Loc); + setRBracketLoc(Loc); + setSizeExpr(NULL); + } + + QualType getInnerType() const { return getTypePtr()->getElementType(); } +}; + +class ConstantArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + ConstantArrayTypeLoc, + ConstantArrayType> { +}; + +class IncompleteArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + IncompleteArrayTypeLoc, + IncompleteArrayType> { +}; + +class DependentSizedArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + DependentSizedArrayTypeLoc, + DependentSizedArrayType> { + +}; + +class VariableArrayTypeLoc : + public InheritingConcreteTypeLoc<ArrayTypeLoc, + VariableArrayTypeLoc, + VariableArrayType> { +}; + + +// Location information for a TemplateName. Rudimentary for now. +struct TemplateNameLocInfo { + SourceLocation NameLoc; +}; + +struct TemplateSpecializationLocInfo : TemplateNameLocInfo { + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; +}; + +class TemplateSpecializationTypeLoc : + public ConcreteTypeLoc<UnqualTypeLoc, + TemplateSpecializationTypeLoc, + TemplateSpecializationType, + TemplateSpecializationLocInfo> { +public: + SourceLocation getLAngleLoc() const { + return getLocalData()->LAngleLoc; + } + void setLAngleLoc(SourceLocation Loc) { + getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return getLocalData()->RAngleLoc; + } + void setRAngleLoc(SourceLocation Loc) { + getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumArgs() const { + return getTypePtr()->getNumArgs(); + } + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { +#ifndef NDEBUG + AI.validateForArgument(getTypePtr()->getArg(i)); +#endif + getArgInfos()[i] = AI; + } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { + return getArgInfos()[i]; + } + + TemplateArgumentLoc getArgLoc(unsigned i) const { + return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + } + + SourceLocation getTemplateNameLoc() const { + return getLocalData()->NameLoc; + } + void setTemplateNameLoc(SourceLocation Loc) { + getLocalData()->NameLoc = Loc; + } + + /// \brief - Copy the location information from the given info. + void copy(TemplateSpecializationTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + + // We're potentially copying Expr references here. We don't + // bother retaining them because TypeSourceInfos live forever, so + // as long as the Expr was retained when originally written into + // the TypeLoc, we're okay. + memcpy(Data, Loc.Data, size); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getTemplateNameLoc(), getRAngleLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setLAngleLoc(Loc); + setRAngleLoc(Loc); + setTemplateNameLoc(Loc); + + for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { + TemplateArgumentLocInfo Info; +#ifndef NDEBUG + // If asserts are enabled, be sure to initialize the argument + // loc with the right kind of pointer. + switch (getTypePtr()->getArg(i).getKind()) { + case TemplateArgument::Expression: + case TemplateArgument::Declaration: + Info = TemplateArgumentLocInfo((Expr*) 0); + break; + + case TemplateArgument::Type: + Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0); + break; + + case TemplateArgument::Template: + Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + break; + + case TemplateArgument::Integral: + case TemplateArgument::Pack: + case TemplateArgument::Null: + // K_None is fine. + break; + } +#endif + getArgInfos()[i] = Info; + } + } + + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(TemplateArgumentLocInfo); + } + +private: + TemplateArgumentLocInfo *getArgInfos() const { + return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); + } +}; + +//===----------------------------------------------------------------------===// +// +// All of these need proper implementations. +// +//===----------------------------------------------------------------------===// + +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + VectorTypeLoc, + VectorType> { +}; + +// FIXME: size expression and attribute locations. +class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, + ExtVectorTypeLoc, + ExtVectorType> { +}; + +// FIXME: attribute locations. +// For some reason, this isn't a subtype of VectorType. +class DependentSizedExtVectorTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DependentSizedExtVectorTypeLoc, + DependentSizedExtVectorType> { +}; + +// FIXME: location of the '_Complex' keyword. +class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + ComplexTypeLoc, + ComplexType> { +}; + +struct TypeofLocInfo { + SourceLocation TypeofLoc; + SourceLocation LParenLoc; + SourceLocation RParenLoc; +}; + +struct TypeOfExprTypeLocInfo : public TypeofLocInfo { +}; + +struct TypeOfTypeLocInfo : public TypeofLocInfo { + TypeSourceInfo* UnderlyingTInfo; +}; + +template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> +class TypeofLikeTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { +public: + SourceLocation getTypeofLoc() const { + return this->getLocalData()->TypeofLoc; + } + void setTypeofLoc(SourceLocation Loc) { + this->getLocalData()->TypeofLoc = Loc; + } + + SourceLocation getLParenLoc() const { + return this->getLocalData()->LParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + this->getLocalData()->LParenLoc = Loc; + } + + SourceLocation getRParenLoc() const { + return this->getLocalData()->RParenLoc; + } + void setRParenLoc(SourceLocation Loc) { + this->getLocalData()->RParenLoc = Loc; + } + + SourceRange getParensRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + void setParensRange(SourceRange range) { + setLParenLoc(range.getBegin()); + setRParenLoc(range.getEnd()); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getTypeofLoc(), getRParenLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setTypeofLoc(Loc); + setLParenLoc(Loc); + setRParenLoc(Loc); + } +}; + +class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc, + TypeOfExprType, + TypeOfExprTypeLocInfo> { +public: + Expr* getUnderlyingExpr() const { + return getTypePtr()->getUnderlyingExpr(); + } + // Reimplemented to account for GNU/C++ extension + // typeof unary-expression + // where there are no parentheses. + SourceRange getLocalSourceRange() const; +}; + +class TypeOfTypeLoc + : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { +public: + QualType getUnderlyingType() const { + return this->getTypePtr()->getUnderlyingType(); + } + TypeSourceInfo* getUnderlyingTInfo() const { + return this->getLocalData()->UnderlyingTInfo; + } + void setUnderlyingTInfo(TypeSourceInfo* TI) const { + this->getLocalData()->UnderlyingTInfo = TI; + } +}; + +// FIXME: location of the 'decltype' and parens. +class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DecltypeTypeLoc, + DecltypeType> { +}; + +struct ElaboratedLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; +}; + +class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ElaboratedTypeLoc, + ElaboratedType, + ElaboratedLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + if (getQualifierRange().getEnd().isValid()) + return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + else + return SourceRange(getKeywordLoc()); + else + return getQualifierRange(); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + } + + TypeLoc getNamedTypeLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return getTypePtr()->getNamedType(); + } + + void copy(ElaboratedTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } +}; + +struct DependentNameLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; + SourceLocation NameLoc; +}; + +class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + DependentNameTypeLoc, + DependentNameType, + DependentNameLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + return SourceRange(getKeywordLoc(), getNameLoc()); + else + return SourceRange(getQualifierRange().getBegin(), getNameLoc()); + } + + void copy(DependentNameTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + setNameLoc(Loc); + } +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLocBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLocBuilder.h new file mode 100644 index 0000000..e729488 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLocBuilder.h @@ -0,0 +1,148 @@ +//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H +#define LLVM_CLANG_AST_TYPELOCBUILDER_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" + +namespace clang { + +class TypeLocBuilder { + enum { InlineCapacity = 8 * sizeof(SourceLocation) }; + + /// The underlying location-data buffer. Data grows from the end + /// of the buffer backwards. + char *Buffer; + + /// The capacity of the current buffer. + size_t Capacity; + + /// The index of the first occupied byte in the buffer. + size_t Index; + +#ifndef NDEBUG + /// The last type pushed on this builder. + QualType LastTy; +#endif + + /// The inline buffer. + char InlineBuffer[InlineCapacity]; + + public: + TypeLocBuilder() + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) + {} + + ~TypeLocBuilder() { + if (Buffer != InlineBuffer) + delete[] Buffer; + } + + /// Ensures that this buffer has at least as much capacity as described. + void reserve(size_t Requested) { + if (Requested > Capacity) + // For now, match the request exactly. + grow(Requested); + } + + /// Pushes a copy of the given TypeLoc onto this builder. The builder + /// must be empty for this to work. + void pushFullCopy(TypeLoc L) { +#ifndef NDEBUG + assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder"); + LastTy = L.getNextTypeLoc().getType(); +#endif + assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder"); + + unsigned Size = L.getFullDataSize(); + TypeLoc Copy = pushImpl(L.getType(), Size); + memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); + } + + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs + /// previously retrieved from this builder. + TypeSpecTypeLoc pushTypeSpec(QualType T) { + size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; + return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + } + + + /// Pushes space for a new TypeLoc of the given type. Invalidates + /// any TypeLocs previously retrieved from this builder. + template <class TyLocType> TyLocType push(QualType T) { + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + return cast<TyLocType>(pushImpl(T, LocalSize)); + } + + /// Creates a TypeSourceInfo for the given type. + TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + +private: + TypeLoc pushImpl(QualType T, size_t LocalSize) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + Index -= LocalSize; + + return TypeLoc(T, &Buffer[Index]); + } + + /// Grow to the given capacity. + void grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; + } +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def new file mode 100644 index 0000000..4590e48 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def @@ -0,0 +1,41 @@ +//===-- TypeLocNodes.def - Metadata about TypeLoc wrappers ------*- 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 TypeLoc info database. Each node is +// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc") +// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc +// are associated +// +// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is +// provided, there will be exactly one of these, Qualified. +// +// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass. +// +// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc. +// +//===----------------------------------------------------------------------===// + +#ifndef UNQUAL_TYPELOC +# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base) +#endif + +#ifndef ABSTRACT_TYPELOC +# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base) +#endif + +TYPELOC(Qualified, TypeLoc) +#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc) +#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc) +#include "clang/AST/TypeNodes.def" + +#undef DECLARATOR_TYPELOC +#undef TYPESPEC_TYPELOC +#undef ABSTRACT_TYPELOC +#undef UNQUAL_TYPELOC +#undef TYPELOC diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h new file mode 100644 index 0000000..50fc439 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h @@ -0,0 +1,62 @@ +//===--- TypeLocVisitor.h - Visitor for TypeLoc subclasses ------*- 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 TypeLocVisitor interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_TYPELOCVISITOR_H +#define LLVM_CLANG_AST_TYPELOCVISITOR_H + +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeVisitor.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { + +#define DISPATCH(CLASSNAME) \ + return static_cast<ImplClass*>(this)-> \ + Visit##CLASSNAME(cast<CLASSNAME>(TyLoc)) + +template<typename ImplClass, typename RetTy=void> +class TypeLocVisitor { +public: + RetTy Visit(TypeLoc TyLoc) { + switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" + } + llvm_unreachable("unexpected type loc class!"); + } + + RetTy Visit(UnqualTypeLoc TyLoc) { + switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" + } + llvm_unreachable("unexpected type loc class!"); + } + +#define TYPELOC(CLASS, PARENT) \ + RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + DISPATCH(PARENT); \ + } +#include "clang/AST/TypeLocNodes.def" + + RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_TYPELOCVISITOR_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def new file mode 100644 index 0000000..02508af --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def @@ -0,0 +1,119 @@ +//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- 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 AST type info database. Each type node is +// enumerated by providing its name (e.g., "Builtin" or "Enum") and +// base class (e.g., "Type" or "TagType"). Depending on where in the +// abstract syntax tree the type will show up, the enumeration uses +// one of four different macros: +// +// TYPE(Class, Base) - A type that can show up anywhere in the AST, +// and might be dependent, canonical, or non-canonical. All clients +// will need to understand these types. +// +// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in +// the type hierarchy but has no concrete instances. +// +// NON_CANONICAL_TYPE(Class, Base) - A type that can show up +// anywhere in the AST but will never be a part of a canonical +// type. Clients that only need to deal with canonical types +// (ignoring, e.g., typedefs and other type alises used for +// pretty-printing) can ignore these types. +// +// DEPENDENT_TYPE(Class, Base) - A type that will only show up +// within a C++ template that has not been instantiated, e.g., a +// type that is always dependent. Clients that do not need to deal +// with uninstantiated C++ templates can ignore these types. +// +// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that +// is non-canonical unless it is dependent. Defaults to TYPE because +// it is neither reliably dependent nor reliably non-canonical. +// +// There is a sixth macro, independent of the others. Most clients +// will not need to use it. +// +// LEAF_TYPE(Class) - A type that never has inner types. Clients +// which can operate on such types more efficiently may wish to do so. +// +//===----------------------------------------------------------------------===// + +#ifndef ABSTRACT_TYPE +# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base) +#endif + +#ifndef NON_CANONICAL_TYPE +# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base) +#endif + +#ifndef DEPENDENT_TYPE +# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) +#endif + +#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE +# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) +#endif + +TYPE(Builtin, Type) +TYPE(Complex, Type) +TYPE(Pointer, Type) +TYPE(BlockPointer, Type) +ABSTRACT_TYPE(Reference, Type) +TYPE(LValueReference, ReferenceType) +TYPE(RValueReference, ReferenceType) +TYPE(MemberPointer, Type) +ABSTRACT_TYPE(Array, Type) +TYPE(ConstantArray, ArrayType) +TYPE(IncompleteArray, ArrayType) +TYPE(VariableArray, ArrayType) +DEPENDENT_TYPE(DependentSizedArray, ArrayType) +DEPENDENT_TYPE(DependentSizedExtVector, Type) +TYPE(Vector, Type) +TYPE(ExtVector, VectorType) +ABSTRACT_TYPE(Function, Type) +TYPE(FunctionProto, FunctionType) +TYPE(FunctionNoProto, FunctionType) +DEPENDENT_TYPE(UnresolvedUsing, Type) +NON_CANONICAL_TYPE(Typedef, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) +ABSTRACT_TYPE(Tag, Type) +TYPE(Record, TagType) +TYPE(Enum, TagType) +NON_CANONICAL_TYPE(Elaborated, Type) +DEPENDENT_TYPE(TemplateTypeParm, Type) +NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) +DEPENDENT_TYPE(InjectedClassName, Type) +DEPENDENT_TYPE(DependentName, Type) +TYPE(ObjCObject, Type) +TYPE(ObjCInterface, ObjCObjectType) +TYPE(ObjCObjectPointer, Type) + +#ifdef LAST_TYPE +LAST_TYPE(ObjCObjectPointer) +#undef LAST_TYPE +#endif + +// These types are always leaves in the type hierarchy. +#ifdef LEAF_TYPE +LEAF_TYPE(Enum) +LEAF_TYPE(Builtin) +LEAF_TYPE(Record) +LEAF_TYPE(InjectedClassName) +LEAF_TYPE(ObjCInterface) +LEAF_TYPE(TemplateTypeParm) +#undef LEAF_TYPE +#endif + +#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE +#undef DEPENDENT_TYPE +#undef NON_CANONICAL_TYPE +#undef ABSTRACT_TYPE +#undef TYPE diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h new file mode 100644 index 0000000..1a050d2 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h @@ -0,0 +1,56 @@ +//===-------------- TypeOrdering.h - Total ordering for types -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a function objects and specializations that +// allow QualType values to be sorted, used in std::maps, std::sets, +// llvm::DenseMaps, and llvm::DenseSets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TYPE_ORDERING_H +#define LLVM_CLANG_TYPE_ORDERING_H + +#include "clang/AST/Type.h" +#include <functional> + +namespace clang { + +/// QualTypeOrdering - Function object that provides a total ordering +/// on QualType values. +struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> { + bool operator()(QualType T1, QualType T2) const { + return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); + } +}; + +} + +namespace llvm { + template<class> struct DenseMapInfo; + + template<> struct DenseMapInfo<clang::QualType> { + static inline clang::QualType getEmptyKey() { return clang::QualType(); } + + static inline clang::QualType getTombstoneKey() { + using clang::QualType; + return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1)); + } + + static unsigned getHashValue(clang::QualType Val) { + return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^ + ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9)); + } + + static bool isEqual(clang::QualType LHS, clang::QualType RHS) { + return LHS == RHS; + } + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h new file mode 100644 index 0000000..5c9c5285 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h @@ -0,0 +1,52 @@ +//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- 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 TypeVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPEVISITOR_H +#define LLVM_CLANG_AST_TYPEVISITOR_H + +#include "clang/AST/Type.h" + +namespace clang { + +#define DISPATCH(CLASS) \ + return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T)) + +template<typename ImplClass, typename RetTy=void> +class TypeVisitor { +public: + RetTy Visit(Type *T) { + // Top switch stmt: dispatch to VisitFooType for each FooType. + switch (T->getTypeClass()) { + default: assert(0 && "Unknown type class!"); +#define ABSTRACT_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type); +#include "clang/AST/TypeNodes.def" + } + } + + // If the implementation chooses not to implement a certain visit method, fall + // back on superclass. +#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { \ + DISPATCH(PARENT); \ +} +#include "clang/AST/TypeNodes.def" + + // Base case, ignore it. :) + RetTy VisitType(Type*) { return RetTy(); } +}; + +#undef DISPATCH + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h new file mode 100644 index 0000000..a548b0b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h @@ -0,0 +1,186 @@ +//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- 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 UnresolvedSet class, which is used to store +// collections of declarations in the AST. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H +#define LLVM_CLANG_AST_UNRESOLVEDSET_H + +#include <iterator> +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/DeclAccessPair.h" + +namespace clang { + +/// The iterator over UnresolvedSets. Serves as both the const and +/// non-const iterator. +class UnresolvedSetIterator { +private: + typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy; + typedef DeclsTy::iterator IteratorTy; + + IteratorTy ir; + + friend class UnresolvedSetImpl; + friend class OverloadExpr; + explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {} + explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) : + ir(const_cast<DeclsTy::iterator>(ir)) {} + + IteratorTy getIterator() const { return ir; } + +public: + UnresolvedSetIterator() {} + + typedef std::iterator_traits<IteratorTy>::difference_type difference_type; + typedef NamedDecl *value_type; + typedef NamedDecl **pointer; + typedef NamedDecl *reference; + typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category; + + NamedDecl *getDecl() const { return ir->getDecl(); } + AccessSpecifier getAccess() const { return ir->getAccess(); } + void setAccess(AccessSpecifier AS) { ir->setAccess(AS); } + DeclAccessPair getPair() const { return *ir; } + + NamedDecl *operator*() const { return getDecl(); } + + UnresolvedSetIterator &operator++() { ++ir; return *this; } + UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); } + UnresolvedSetIterator &operator--() { --ir; return *this; } + UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); } + + UnresolvedSetIterator &operator+=(difference_type d) { + ir += d; return *this; + } + UnresolvedSetIterator operator+(difference_type d) const { + return UnresolvedSetIterator(ir + d); + } + UnresolvedSetIterator &operator-=(difference_type d) { + ir -= d; return *this; + } + UnresolvedSetIterator operator-(difference_type d) const { + return UnresolvedSetIterator(ir - d); + } + value_type operator[](difference_type d) const { return *(*this + d); } + + difference_type operator-(const UnresolvedSetIterator &o) const { + return ir - o.ir; + } + + bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; } + bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; } + bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; } + bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; } + bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; } + bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; } +}; + +/// UnresolvedSet - A set of unresolved declarations. +class UnresolvedSetImpl { + typedef UnresolvedSetIterator::DeclsTy DeclsTy; + + // Don't allow direct construction, and only permit subclassing by + // UnresolvedSet. +private: + template <unsigned N> friend class UnresolvedSet; + UnresolvedSetImpl() {} + UnresolvedSetImpl(const UnresolvedSetImpl &) {} + +public: + // We don't currently support assignment through this iterator, so we might + // as well use the same implementation twice. + typedef UnresolvedSetIterator iterator; + typedef UnresolvedSetIterator const_iterator; + + iterator begin() { return iterator(decls().begin()); } + iterator end() { return iterator(decls().end()); } + + const_iterator begin() const { return const_iterator(decls().begin()); } + const_iterator end() const { return const_iterator(decls().end()); } + + void addDecl(NamedDecl *D) { + addDecl(D, AS_none); + } + + void addDecl(NamedDecl *D, AccessSpecifier AS) { + decls().push_back(DeclAccessPair::make(D, AS)); + } + + /// Replaces the given declaration with the new one, once. + /// + /// \return true if the set changed + bool replace(const NamedDecl* Old, NamedDecl *New) { + for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I) + if (I->getDecl() == Old) + return (I->setDecl(New), true); + return false; + } + + /// Replaces the declaration at the given iterator with the new one, + /// preserving the original access bits. + void replace(iterator I, NamedDecl *New) { + I.ir->setDecl(New); + } + + void replace(iterator I, NamedDecl *New, AccessSpecifier AS) { + I.ir->set(New, AS); + } + + void erase(unsigned I) { + decls()[I] = decls().back(); + decls().pop_back(); + } + + void erase(iterator I) { + *I.ir = decls().back(); + decls().pop_back(); + } + + void setAccess(iterator I, AccessSpecifier AS) { + I.ir->setAccess(AS); + } + + void clear() { decls().clear(); } + void set_size(unsigned N) { decls().set_size(N); } + + bool empty() const { return decls().empty(); } + unsigned size() const { return decls().size(); } + + void append(iterator I, iterator E) { + decls().append(I.ir, E.ir); + } + + DeclAccessPair &operator[](unsigned I) { return decls()[I]; } + const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; } + +private: + // These work because the only permitted subclass is UnresolvedSetImpl + + DeclsTy &decls() { + return *reinterpret_cast<DeclsTy*>(this); + } + const DeclsTy &decls() const { + return *reinterpret_cast<const DeclsTy*>(this); + } +}; + +/// A set of unresolved declarations +template <unsigned InlineCapacity> class UnresolvedSet : + public UnresolvedSetImpl { + llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls; +}; + + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h b/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h new file mode 100644 index 0000000..5ee40e0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h @@ -0,0 +1,105 @@ +//===-- 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; + + 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> +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/Analysis/Analyses/LiveVariables.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h new file mode 100644 index 0000000..44ab080 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h @@ -0,0 +1,121 @@ +//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- 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 Live Variables analysis for source-level CFGs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIVEVARIABLES_H +#define LLVM_CLANG_LIVEVARIABLES_H + +#include "clang/AST/Decl.h" +#include "clang/Analysis/Support/BlkExprDeclBitVector.h" +#include "clang/Analysis/FlowSensitive/DataflowValues.h" + +namespace clang { + +class Stmt; +class DeclRefExpr; +class SourceManager; +class AnalysisContext; + +struct LiveVariables_ValueTypes { + + struct ObserverTy; + + // We keep dataflow state for declarations and block-level expressions; + typedef StmtDeclBitVector_Types::ValTy ValTy; + + // We need to keep track of both declarations and CFGBlock-level expressions, + // (so that we don't explore such expressions twice). We also want + // to compute liveness information for block-level expressions, since these + // act as "temporary" values. + + struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { + ObserverTy* Observer; + ValTy AlwaysLive; + AnalysisContext *AC; + + AnalysisDataTy() : Observer(NULL), AC(NULL) {} + }; + + //===-----------------------------------------------------===// + // ObserverTy - Observer for uninitialized values queries. + //===-----------------------------------------------------===// + + struct ObserverTy { + virtual ~ObserverTy() {} + + /// ObserveStmt - A callback invoked right before invoking the + /// liveness transfer function on the given statement. + virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD, + const ValTy& V) {} + + virtual void ObserverKill(DeclRefExpr* DR) {} + }; +}; + +class LiveVariables : public DataflowValues<LiveVariables_ValueTypes, + dataflow::backward_analysis_tag> { + + +public: + typedef LiveVariables_ValueTypes::ObserverTy ObserverTy; + + LiveVariables(AnalysisContext &AC); + + /// IsLive - Return true if a variable is live at the end of a + /// specified block. + bool isLive(const CFGBlock* B, const VarDecl* D) const; + + /// IsLive - Returns true if a variable is live at the beginning of the + /// the statement. This query only works if liveness information + /// has been recorded at the statement level (see runOnAllBlocks), and + /// only returns liveness information for block-level expressions. + bool isLive(const Stmt* S, const VarDecl* D) const; + + /// IsLive - Returns true the block-level expression "value" is live + /// before the given block-level expression (see runOnAllBlocks). + bool isLive(const Stmt* Loc, const Stmt* StmtVal) const; + + /// IsLive - Return true if a variable is live according to the + /// provided livness bitvector. + bool isLive(const ValTy& V, const VarDecl* D) const; + + /// dumpLiveness - Print to stderr the liveness information encoded + /// by a specified bitvector. + void dumpLiveness(const ValTy& V, const SourceManager& M) const; + + /// dumpBlockLiveness - Print to stderr the liveness information + /// associated with each basic block. + void dumpBlockLiveness(const SourceManager& M) const; + + /// getNumDecls - Return the number of variables (declarations) that + /// whose liveness status is being tracked by the dataflow + /// analysis. + unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); } + + /// IntializeValues - This routine can perform extra initialization, but + /// for LiveVariables this does nothing since all that logic is in + /// the constructor. + void InitializeValues(const CFG& cfg) {} + + void runOnCFG(CFG& cfg); + + /// runOnAllBlocks - Propagate the dataflow values once for each block, + /// starting from the current dataflow values. 'recordStmtValues' indicates + /// whether the method should store dataflow values per each individual + /// block-level expression. + void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs, + bool recordStmtValues=false); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PrintfFormatString.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PrintfFormatString.h new file mode 100644 index 0000000..e4f7c57 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PrintfFormatString.h @@ -0,0 +1,313 @@ +//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Handling of format string in printf and friends. The structure of format +// strings for fprintf() are described in C99 7.19.6.1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FPRINTF_FORMAT_H +#define LLVM_CLANG_FPRINTF_FORMAT_H + +#include "clang/AST/CanonicalType.h" + +namespace clang { + +class ASTContext; + +namespace analyze_printf { + +class ArgTypeResult { +public: + enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CStrTy, + WCStrTy }; +private: + const Kind K; + QualType T; + ArgTypeResult(bool) : K(InvalidTy) {} +public: + ArgTypeResult(Kind k = UnknownTy) : K(k) {} + ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} + ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} + + static ArgTypeResult Invalid() { return ArgTypeResult(true); } + + bool isValid() const { return K != InvalidTy; } + + const QualType *getSpecificType() const { + return K == SpecificTy ? &T : 0; + } + + bool matchesType(ASTContext &C, QualType argTy) const; + + bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } + + QualType getRepresentativeType(ASTContext &C) const; +}; + +class ConversionSpecifier { +public: + enum Kind { + InvalidSpecifier = 0, + // C99 conversion specifiers. + dArg, // 'd' + iArg, // 'i', + oArg, // 'o', + uArg, // 'u', + xArg, // 'x', + XArg, // 'X', + fArg, // 'f', + FArg, // 'F', + eArg, // 'e', + EArg, // 'E', + gArg, // 'g', + GArg, // 'G', + aArg, // 'a', + AArg, // 'A', + IntAsCharArg, // 'c' + CStrArg, // 's' + VoidPtrArg, // 'p' + OutIntPtrArg, // 'n' + PercentArg, // '%' + // MacOS X unicode extensions. + CArg, // 'C' + UnicodeStrArg, // 'S' + // Objective-C specific specifiers. + ObjCObjArg, // '@' + // GlibC specific specifiers. + PrintErrno, // 'm' + // Specifier ranges. + IntArgBeg = dArg, + IntArgEnd = iArg, + UIntArgBeg = oArg, + UIntArgEnd = XArg, + DoubleArgBeg = fArg, + DoubleArgEnd = AArg, + C99Beg = IntArgBeg, + C99End = DoubleArgEnd, + ObjCBeg = ObjCObjArg, + ObjCEnd = ObjCObjArg + }; + + ConversionSpecifier() + : Position(0), kind(InvalidSpecifier) {} + + ConversionSpecifier(const char *pos, Kind k) + : Position(pos), kind(k) {} + + const char *getStart() const { + return Position; + } + + llvm::StringRef getCharacters() const { + return llvm::StringRef(getStart(), getLength()); + } + + bool consumesDataArgument() const { + switch (kind) { + case PercentArg: + case PrintErrno: + return false; + default: + return true; + } + } + + bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } + bool isIntArg() const { return kind >= dArg && kind <= iArg; } + bool isUIntArg() const { return kind >= oArg && kind <= XArg; } + bool isDoubleArg() const { return kind >= fArg && kind <= AArg; } + Kind getKind() const { return kind; } + unsigned getLength() const { + // Conversion specifiers currently only are represented by + // single characters, but we be flexible. + return 1; + } + +private: + const char *Position; + Kind kind; +}; + +enum LengthModifier { + None, + AsChar, // 'hh' + AsShort, // 'h' + AsLong, // 'l' + AsLongLong, // 'll', 'q' (BSD, deprecated) + AsIntMax, // 'j' + AsSizeT, // 'z' + AsPtrDiff, // 't' + AsLongDouble, // 'L' + AsWideChar = AsLong // for '%ls' +}; + +class OptionalAmount { +public: + enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; + + OptionalAmount(HowSpecified h, unsigned i, const char *st) + : start(st), hs(h), amt(i) {} + + OptionalAmount(bool b = true) + : start(0), hs(b ? NotSpecified : Invalid), amt(0) {} + + bool isInvalid() const { + return hs == Invalid; + } + + HowSpecified getHowSpecified() const { return hs; } + + bool hasDataArgument() const { return hs == Arg; } + + unsigned getArgIndex() const { + assert(hasDataArgument()); + return amt; + } + + unsigned getConstantAmount() const { + assert(hs == Constant); + return amt; + } + + const char *getStart() const { + return start; + } + + ArgTypeResult getArgType(ASTContext &Ctx) const; + +private: + const char *start; + HowSpecified hs; + unsigned amt; +}; + +class FormatSpecifier { + LengthModifier LM; + unsigned IsLeftJustified : 1; + unsigned HasPlusPrefix : 1; + unsigned HasSpacePrefix : 1; + unsigned HasAlternativeForm : 1; + unsigned HasLeadingZeroes : 1; + /// Positional arguments, an IEEE extension: + /// IEEE Std 1003.1, 2004 Edition + /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html + unsigned UsesPositionalArg : 1; + unsigned argIndex; + ConversionSpecifier CS; + OptionalAmount FieldWidth; + OptionalAmount Precision; +public: + FormatSpecifier() : LM(None), + IsLeftJustified(0), HasPlusPrefix(0), HasSpacePrefix(0), + HasAlternativeForm(0), HasLeadingZeroes(0), UsesPositionalArg(0), + argIndex(0) {} + + static FormatSpecifier Parse(const char *beg, const char *end); + + // Methods for incrementally constructing the FormatSpecifier. + void setConversionSpecifier(const ConversionSpecifier &cs) { + CS = cs; + } + void setLengthModifier(LengthModifier lm) { + LM = lm; + } + void setIsLeftJustified() { IsLeftJustified = 1; } + void setHasPlusPrefix() { HasPlusPrefix = 1; } + void setHasSpacePrefix() { HasSpacePrefix = 1; } + void setHasAlternativeForm() { HasAlternativeForm = 1; } + void setHasLeadingZeros() { HasLeadingZeroes = 1; } + void setUsesPositionalArg() { UsesPositionalArg = 1; } + + void setArgIndex(unsigned i) { + assert(CS.consumesDataArgument()); + argIndex = i; + } + + unsigned getArgIndex() const { + assert(CS.consumesDataArgument()); + return argIndex; + } + + // Methods for querying the format specifier. + + const ConversionSpecifier &getConversionSpecifier() const { + return CS; + } + + LengthModifier getLengthModifier() const { + return LM; + } + + const OptionalAmount &getFieldWidth() const { + return FieldWidth; + } + + void setFieldWidth(const OptionalAmount &Amt) { + FieldWidth = Amt; + } + + void setPrecision(const OptionalAmount &Amt) { + Precision = Amt; + } + + const OptionalAmount &getPrecision() const { + return Precision; + } + + /// \brief Returns the builtin type that a data argument + /// paired with this format specifier should have. This method + /// 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; + + bool isLeftJustified() const { return (bool) IsLeftJustified; } + bool hasPlusPrefix() const { return (bool) HasPlusPrefix; } + bool hasAlternativeForm() const { return (bool) HasAlternativeForm; } + bool hasLeadingZeros() const { return (bool) HasLeadingZeroes; } + bool hasSpacePrefix() const { return (bool) HasSpacePrefix; } + bool usesPositionalArg() const { return (bool) UsesPositionalArg; } +}; + +enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; + +class FormatStringHandler { +public: + FormatStringHandler() {} + virtual ~FormatStringHandler(); + + virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier, + unsigned specifierLen) {} + + virtual void HandleNullChar(const char *nullCharacter) {} + + virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, + PositionContext p) {} + + virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} + + virtual bool + HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { return true; } + + virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + return true; + } +}; + +bool ParseFormatString(FormatStringHandler &H, + const char *beg, const char *end); + +} // end printf namespace +} // 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 new file mode 100644 index 0000000..e0c84f9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -0,0 +1,55 @@ +//===- ReachableCode.h -----------------------------------------*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A flow-sensitive, path-insensitive analysis of unreachable code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REACHABLECODE_H +#define LLVM_CLANG_REACHABLECODE_H + +#include "clang/Basic/SourceLocation.h" + +//===----------------------------------------------------------------------===// +// Forward declarations. +//===----------------------------------------------------------------------===// + +namespace llvm { + class BitVector; +} + +namespace clang { + class AnalysisContext; + class CFGBlock; +} + +//===----------------------------------------------------------------------===// +// API. +//===----------------------------------------------------------------------===// + +namespace clang { +namespace reachable_code { + +class Callback { +public: + virtual ~Callback() {} + virtual void HandleUnreachable(SourceLocation L, SourceRange R1, + SourceRange R2) = 0; +}; + +/// ScanReachableFromBlock - Mark all blocks reachable from Start. +/// Returns the total number of blocks that were marked reachable. +unsigned ScanReachableFromBlock(const CFGBlock &Start, + llvm::BitVector &Reachable); + +void FindUnreachableCode(AnalysisContext &AC, Callback &CB); + +}} // end namespace clang::reachable_code + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h new file mode 100644 index 0000000..cd771ac --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h @@ -0,0 +1,77 @@ +//===- UninitializedValues.h - unintialized values analysis ----*- 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 the interface for the Unintialized Values analysis, +// a flow-sensitive analysis that detects when variable values are unintialized. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_UNITVALS_H +#define LLVM_CLANG_UNITVALS_H + +#include "clang/Analysis/Support/BlkExprDeclBitVector.h" +#include "clang/Analysis/FlowSensitive/DataflowValues.h" + +namespace clang { + + class BlockVarDecl; + class Expr; + class DeclRefExpr; + class VarDecl; + +/// UninitializedValues_ValueTypes - Utility class to wrap type declarations +/// for dataflow values and dataflow analysis state for the +/// Unitialized Values analysis. +class UninitializedValues_ValueTypes { +public: + + struct ObserverTy; + + struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { + AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} + virtual ~AnalysisDataTy() {} + + ObserverTy* Observer; + bool FullUninitTaint; + }; + + typedef StmtDeclBitVector_Types::ValTy ValTy; + + //===--------------------------------------------------------------------===// + // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized + // value. + //===--------------------------------------------------------------------===// + + struct ObserverTy { + virtual ~ObserverTy(); + virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, + DeclRefExpr* DR, VarDecl* VD) = 0; + }; +}; + +/// UninitializedValues - Objects of this class encapsulate dataflow analysis +/// information regarding what variable declarations in a function are +/// potentially unintialized. +class UninitializedValues : + public DataflowValues<UninitializedValues_ValueTypes> { +public: + typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy; + + UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); } + + /// IntializeValues - Create initial dataflow values and meta data for + /// a given CFG. This is intended to be called by the dataflow solver. + void InitializeValues(const CFG& cfg); +}; + + +void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, + bool FullUninitTaint=false); +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h new file mode 100644 index 0000000..9ebd93b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h @@ -0,0 +1,263 @@ +//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- 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 AnalysisContext, a class that manages the analysis context +// data for path sensitive analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H +#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H + +#include "clang/AST/Decl.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" + +namespace clang { + +class Decl; +class Stmt; +class CFG; +class CFGBlock; +class LiveVariables; +class ParentMap; +class ImplicitParamDecl; +class LocationContextManager; +class StackFrameContext; + +/// AnalysisContext contains the context data for the function or method under +/// analysis. +class AnalysisContext { + const Decl *D; + + // AnalysisContext owns the following data. + CFG *cfg; + bool builtCFG; + LiveVariables *liveness; + ParentMap *PM; + llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + llvm::BumpPtrAllocator A; + bool AddEHEdges; +public: + AnalysisContext(const Decl *d, bool addehedges = false) + : D(d), cfg(0), builtCFG(false), liveness(0), PM(0), + ReferencedBlockVars(0), AddEHEdges(addehedges) {} + + ~AnalysisContext(); + + ASTContext &getASTContext() { return D->getASTContext(); } + const Decl *getDecl() { return D; } + /// 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 AddEHEdges; } + Stmt *getBody(); + CFG *getCFG(); + ParentMap &getParentMap(); + LiveVariables *getLiveVariables(); + + typedef const VarDecl * const * referenced_decls_iterator; + + std::pair<referenced_decls_iterator, referenced_decls_iterator> + getReferencedBlockVars(const BlockDecl *BD); + + /// Return the ImplicitParamDecl* associated with 'self' if this + /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. + const ImplicitParamDecl *getSelfDecl() const; +}; + +class AnalysisContextManager { + typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; + ContextMap Contexts; +public: + ~AnalysisContextManager(); + + AnalysisContext *getContext(const Decl *D); + + // Discard all previously created AnalysisContexts. + void clear(); +}; + +class LocationContext : public llvm::FoldingSetNode { +public: + enum ContextKind { StackFrame, Scope, Block }; + +private: + ContextKind Kind; + AnalysisContext *Ctx; + const LocationContext *Parent; + +protected: + LocationContext(ContextKind k, AnalysisContext *ctx, + const LocationContext *parent) + : Kind(k), Ctx(ctx), Parent(parent) {} + +public: + virtual ~LocationContext(); + + ContextKind getKind() const { return Kind; } + + AnalysisContext *getAnalysisContext() const { return Ctx; } + + const LocationContext *getParent() const { return Parent; } + + bool isParentOf(const LocationContext *LC) const; + + const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } + + CFG *getCFG() const { return getAnalysisContext()->getCFG(); } + + LiveVariables *getLiveVariables() const { + return getAnalysisContext()->getLiveVariables(); + } + + ParentMap &getParentMap() const { + return getAnalysisContext()->getParentMap(); + } + + const ImplicitParamDecl *getSelfDecl() const { + return Ctx->getSelfDecl(); + } + + const StackFrameContext *getCurrentStackFrame() const; + const StackFrameContext * + getStackFrameForDeclContext(const DeclContext *DC) const; + + virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; + + static bool classof(const LocationContext*) { return true; } + +public: + static void ProfileCommon(llvm::FoldingSetNodeID &ID, + ContextKind ck, + AnalysisContext *ctx, + const LocationContext *parent, + const void* data); +}; + +class StackFrameContext : public LocationContext { + // The callsite where this stack frame is established. + const Stmt *CallSite; + + // The parent block of the callsite. + const CFGBlock *Block; + + // The index of the callsite in the CFGBlock. + unsigned Index; + + friend class LocationContextManager; + StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, + const Stmt *s, const CFGBlock *blk, unsigned idx) + : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), + Index(idx) {} + +public: + ~StackFrameContext() {} + + const Stmt *getCallSite() const { return CallSite; } + + const CFGBlock *getCallSiteBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const Stmt *s, + const CFGBlock *blk, unsigned idx) { + ProfileCommon(ID, StackFrame, ctx, parent, s); + ID.AddPointer(blk); + ID.AddInteger(idx); + } + + static bool classof(const LocationContext* Ctx) { + return Ctx->getKind() == StackFrame; + } +}; + +class ScopeContext : public LocationContext { + const Stmt *Enter; + + friend class LocationContextManager; + ScopeContext(AnalysisContext *ctx, const LocationContext *parent, + const Stmt *s) + : LocationContext(Scope, ctx, parent), Enter(s) {} + +public: + ~ScopeContext() {} + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const Stmt *s) { + ProfileCommon(ID, Scope, ctx, parent, s); + } + + static bool classof(const LocationContext* Ctx) { + return Ctx->getKind() == Scope; + } +}; + +class BlockInvocationContext : public LocationContext { + // FIXME: Add back context-sensivity (we don't want libAnalysis to know + // about MemRegion). + const BlockDecl *BD; + + friend class LocationContextManager; + + BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + const BlockDecl *bd) + : LocationContext(Block, ctx, parent), BD(bd) {} + +public: + ~BlockInvocationContext() {} + + const BlockDecl *getBlockDecl() const { return BD; } + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const BlockDecl *bd) { + ProfileCommon(ID, Block, ctx, parent, bd); + } + + static bool classof(const LocationContext* Ctx) { + return Ctx->getKind() == Block; + } +}; + +class LocationContextManager { + llvm::FoldingSet<LocationContext> Contexts; +public: + ~LocationContextManager(); + + const StackFrameContext *getStackFrame(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s, const CFGBlock *blk, + unsigned idx); + + const ScopeContext *getScope(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s); + + /// Discard all previously created LocationContext objects. + void clear(); +private: + template <typename LOC, typename DATA> + const LOC *getLocationContext(AnalysisContext *ctx, + const LocationContext *parent, + const DATA *d); +}; + +} // 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 new file mode 100644 index 0000000..e98a3df --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- 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_DIAGNOSTICANALYSIS_H +#define LLVM_CLANG_DIAGNOSTICANALYSIS_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define ANALYSISSTART +#include "clang/Basic/DiagnosticAnalysisKinds.inc" +#undef DIAG + NUM_BUILTIN_ANALYSIS_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h new file mode 100644 index 0000000..b7256c9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h @@ -0,0 +1,512 @@ +//===--- CFG.h - Classes for representing and building CFGs------*- 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 CFG and CFGBuilder classes for representing and +// building Control-Flow Graphs (CFGs) from ASTs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CFG_H +#define LLVM_CLANG_CFG_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "clang/Analysis/Support/BumpVector.h" +#include "clang/Basic/SourceLocation.h" +#include <cassert> + +namespace llvm { + class raw_ostream; +} +namespace clang { + class Decl; + class Stmt; + class Expr; + class CFG; + class PrinterHelper; + class LangOptions; + class ASTContext; + +namespace { +// An element of the CFG for implicit descructor calls implied by the language +// rules. +class Dtor { + // Statement that introduces the variable. + Stmt *S; + // A token which ends the scope, return, goto, throw, }. + SourceLocation Loc; +public: + Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) { + } + SourceLocation getLoc() { return Loc; } + Stmt *getStmt() { return S; } +}; +} + +/// CFGElement - Represents a top-level expression in a basic block. +class CFGElement { + llvm::PointerIntPair<Stmt *, 2> Data; +public: + enum Type { StartScope, EndScope }; + explicit CFGElement() {} + CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {} + CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {} + // CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {} + Stmt *getStmt() const { return Data.getPointer(); } + bool asLValue() const { return Data.getInt() == 1; } + bool asStartScope() const { return Data.getInt() == 2; } + bool asEndScope() const { return Data.getInt() == 3; } + bool asDtor() const { return Data.getInt() == 4; } + operator Stmt*() const { return getStmt(); } + operator bool() const { return getStmt() != 0; } + operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); } +}; + +/// CFGBlock - Represents a single basic block in a source-level CFG. +/// It consists of: +/// +/// (1) A set of statements/expressions (which may contain subexpressions). +/// (2) A "terminator" statement (not in the set of statements). +/// (3) A list of successors and predecessors. +/// +/// Terminator: The terminator represents the type of control-flow that occurs +/// at the end of the basic block. The terminator is a Stmt* referring to an +/// AST node that has control-flow: if-statements, breaks, loops, etc. +/// If the control-flow is conditional, the condition expression will appear +/// within the set of statements in the block (usually the last statement). +/// +/// Predecessors: the order in the set of predecessors is arbitrary. +/// +/// Successors: the order in the set of successors is NOT arbitrary. We +/// currently have the following orderings based on the terminator: +/// +/// Terminator Successor Ordering +/// ----------------------------------------------------- +/// if Then Block; Else Block +/// ? operator LHS expression; RHS expression +/// &&, || expression that uses result of && or ||, RHS +/// +class CFGBlock { + class StatementList { + typedef BumpVector<CFGElement> ImplTy; + ImplTy Impl; + public: + StatementList(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; + + void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + 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(); } + const_iterator end() const { return Impl.rend(); } + reverse_iterator rbegin() { return Impl.begin(); } + reverse_iterator rend() { return Impl.end(); } + const_reverse_iterator rbegin() const { return Impl.begin(); } + const_reverse_iterator rend() const { return Impl.end(); } + + CFGElement operator[](size_t i) const { + assert(i < Impl.size()); + return Impl[Impl.size() - 1 - i]; + } + + size_t size() const { return Impl.size(); } + bool empty() const { return Impl.empty(); } + }; + + /// Stmts - The set of statements in the basic block. + StatementList Stmts; + + /// Label - An (optional) label that prefixes the executable + /// statements in the block. When this variable is non-NULL, it is + /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. + Stmt *Label; + + /// Terminator - The terminator for a basic block that + /// indicates the type of control-flow that occurs between a block + /// and its successors. + Stmt *Terminator; + + /// LoopTarget - Some blocks are used to represent the "loop edge" to + /// the start of a loop from within the loop body. This Stmt* will be + /// refer to the loop statement for such blocks (and be null otherwise). + const Stmt *LoopTarget; + + /// BlockID - A numerical ID assigned to a CFGBlock during construction + /// of the CFG. + unsigned BlockID; + + /// Predecessors/Successors - Keep track of the predecessor / successor + /// CFG blocks. + typedef BumpVector<CFGBlock*> AdjacentBlocks; + AdjacentBlocks Preds; + AdjacentBlocks Succs; + +public: + explicit CFGBlock(unsigned blockid, BumpVectorContext &C) + : Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), + BlockID(blockid), Preds(C, 1), Succs(C, 1) {} + ~CFGBlock() {} + + // Statement iterators + typedef StatementList::iterator iterator; + typedef StatementList::const_iterator const_iterator; + typedef StatementList::reverse_iterator reverse_iterator; + typedef StatementList::const_reverse_iterator const_reverse_iterator; + + CFGElement front() const { return Stmts.front(); } + CFGElement back() const { return Stmts.back(); } + + iterator begin() { return Stmts.begin(); } + iterator end() { return Stmts.end(); } + const_iterator begin() const { return Stmts.begin(); } + const_iterator end() const { return Stmts.end(); } + + reverse_iterator rbegin() { return Stmts.rbegin(); } + reverse_iterator rend() { return Stmts.rend(); } + const_reverse_iterator rbegin() const { return Stmts.rbegin(); } + const_reverse_iterator rend() const { return Stmts.rend(); } + + unsigned size() const { return Stmts.size(); } + bool empty() const { return Stmts.empty(); } + + CFGElement operator[](size_t i) const { return Stmts[i]; } + + // CFG iterators + typedef AdjacentBlocks::iterator pred_iterator; + typedef AdjacentBlocks::const_iterator const_pred_iterator; + typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; + typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; + + typedef AdjacentBlocks::iterator succ_iterator; + typedef AdjacentBlocks::const_iterator const_succ_iterator; + typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; + typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; + + pred_iterator pred_begin() { return Preds.begin(); } + pred_iterator pred_end() { return Preds.end(); } + const_pred_iterator pred_begin() const { return Preds.begin(); } + const_pred_iterator pred_end() const { return Preds.end(); } + + pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); } + pred_reverse_iterator pred_rend() { return Preds.rend(); } + const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } + const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } + + succ_iterator succ_begin() { return Succs.begin(); } + succ_iterator succ_end() { return Succs.end(); } + const_succ_iterator succ_begin() const { return Succs.begin(); } + const_succ_iterator succ_end() const { return Succs.end(); } + + succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); } + succ_reverse_iterator succ_rend() { return Succs.rend(); } + const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } + const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } + + unsigned succ_size() const { return Succs.size(); } + bool succ_empty() const { return Succs.empty(); } + + unsigned pred_size() const { return Preds.size(); } + bool pred_empty() const { return Preds.empty(); } + + // Manipulation of block contents + + void setTerminator(Stmt* Statement) { Terminator = Statement; } + void setLabel(Stmt* Statement) { Label = Statement; } + void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } + + Stmt* getTerminator() { return Terminator; } + const Stmt* getTerminator() const { return Terminator; } + + Stmt* getTerminatorCondition(); + + const Stmt* getTerminatorCondition() const { + return const_cast<CFGBlock*>(this)->getTerminatorCondition(); + } + + const Stmt *getLoopTarget() const { return LoopTarget; } + + bool hasBinaryBranchTerminator() const; + + Stmt* getLabel() { return Label; } + const Stmt* getLabel() const { return Label; } + + unsigned getBlockID() const { return BlockID; } + + void dump(const CFG *cfg, const LangOptions &LO) const; + void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const; + void printTerminator(llvm::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, bool asLValue) { + Stmts.push_back(CFGElement(Statement, asLValue), C); + } + void StartScope(Stmt* S, BumpVectorContext &C) { + Stmts.push_back(CFGElement(S, CFGElement::StartScope), C); + } + void EndScope(Stmt* S, BumpVectorContext &C) { + Stmts.push_back(CFGElement(S, CFGElement::EndScope), C); + } +}; + + +/// CFG - Represents a source-level, intra-procedural CFG that represents the +/// control-flow of a Stmt. The Stmt can represent an entire function body, +/// or a single expression. A CFG will always contain one empty block that +/// represents the Exit point of the CFG. A CFG will also contain a designated +/// Entry block. The CFG solely represents control-flow; it consists of +/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG +/// was constructed from. +class CFG { +public: + //===--------------------------------------------------------------------===// + // CFG Construction & Manipulation. + //===--------------------------------------------------------------------===// + + /// 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, + bool AddEHEdges = false, + bool AddScopes = false /* NOT FULLY IMPLEMENTED. + NOT READY FOR GENERAL USE. */); + + /// createBlock - Create a new block in the CFG. The CFG owns the block; + /// the caller should not directly free it. + CFGBlock* createBlock(); + + /// setEntry - Set the entry block of the CFG. This is typically used + /// only during CFG construction. Most CFG clients expect that the + /// entry block has no predecessors and contains no statements. + void setEntry(CFGBlock *B) { Entry = B; } + + /// setIndirectGotoBlock - Set the block used for indirect goto jumps. + /// This is typically used only during CFG construction. + void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; } + + //===--------------------------------------------------------------------===// + // Block Iterators + //===--------------------------------------------------------------------===// + + typedef BumpVector<CFGBlock*> CFGBlockListTy; + typedef CFGBlockListTy::iterator iterator; + typedef CFGBlockListTy::const_iterator const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + CFGBlock& front() { return *Blocks.front(); } + CFGBlock& back() { return *Blocks.back(); } + + iterator begin() { return Blocks.begin(); } + iterator end() { return Blocks.end(); } + const_iterator begin() const { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + + reverse_iterator rbegin() { return Blocks.rbegin(); } + reverse_iterator rend() { return Blocks.rend(); } + const_reverse_iterator rbegin() const { return Blocks.rbegin(); } + const_reverse_iterator rend() const { return Blocks.rend(); } + + CFGBlock& getEntry() { return *Entry; } + const CFGBlock& getEntry() const { return *Entry; } + CFGBlock& getExit() { return *Exit; } + const CFGBlock& getExit() const { return *Exit; } + + CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; } + const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; } + + //===--------------------------------------------------------------------===// + // Member templates useful for various batch operations over CFGs. + //===--------------------------------------------------------------------===// + + template <typename CALLBACK> + void VisitBlockStmts(CALLBACK& O) const { + for (const_iterator I=begin(), E=end(); I != E; ++I) + for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); + BI != BE; ++BI) + O(*BI); + } + + //===--------------------------------------------------------------------===// + // CFG Introspection. + //===--------------------------------------------------------------------===// + + struct BlkExprNumTy { + const signed Idx; + explicit BlkExprNumTy(signed idx) : Idx(idx) {} + explicit BlkExprNumTy() : Idx(-1) {} + operator bool() const { return Idx >= 0; } + operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; } + }; + + bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); } + BlkExprNumTy getBlkExprNum(const Stmt* S); + unsigned getNumBlkExprs(); + + /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which + /// start at 0). + unsigned getNumBlockIDs() const { return NumBlockIDs; } + + //===--------------------------------------------------------------------===// + // CFG Debugging: Pretty-Printing and Visualization. + //===--------------------------------------------------------------------===// + + void viewCFG(const LangOptions &LO) const; + void print(llvm::raw_ostream& OS, const LangOptions &LO) const; + void dump(const LangOptions &LO) const; + + //===--------------------------------------------------------------------===// + // Internal: constructors and data. + //===--------------------------------------------------------------------===// + + CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), + BlkExprMap(NULL), Blocks(BlkBVC, 10) {} + + ~CFG(); + + llvm::BumpPtrAllocator& getAllocator() { + return BlkBVC.getAllocator(); + } + + BumpVectorContext &getBumpVectorContext() { + return BlkBVC; + } + +private: + CFGBlock* Entry; + CFGBlock* Exit; + CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch + // for indirect gotos + unsigned NumBlockIDs; + + // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h. + // 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; + +}; +} // end namespace clang + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for CFG basic block graphs (source-level CFGs) +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// Implement simplify_type for CFGElement, so that we can dyn_cast from +/// CFGElement to a specific Stmt class. +template <> struct simplify_type<const ::clang::CFGElement> { + typedef ::clang::Stmt* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) { + return Val.getStmt(); + } +}; + +template <> struct simplify_type< ::clang::CFGElement> + : public simplify_type<const ::clang::CFGElement> {}; + +// Traits for: CFGBlock + +template <> struct GraphTraits< ::clang::CFGBlock* > { + typedef ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; + + static NodeType* getEntryNode(::clang::CFGBlock* BB) + { return BB; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->succ_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->succ_end(); } +}; + +template <> struct GraphTraits< const ::clang::CFGBlock* > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; + + static NodeType* getEntryNode(const clang::CFGBlock* BB) + { return BB; } + + static inline ChildIteratorType child_begin(NodeType* N) + { return N->succ_begin(); } + + static inline ChildIteratorType child_end(NodeType* N) + { return N->succ_end(); } +}; + +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse<const ::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(); } +}; + +// Traits for: CFG + +template <> struct GraphTraits< ::clang::CFG* > + : public GraphTraits< ::clang::CFGBlock* > { + + typedef ::clang::CFG::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(); } +}; + +template <> struct GraphTraits<const ::clang::CFG* > + : public GraphTraits<const ::clang::CFGBlock* > { + + typedef ::clang::CFG::const_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(); + } + static nodes_iterator nodes_end( const ::clang::CFG* F) { + return F->end(); + } +}; + +template <> struct GraphTraits<Inverse<const ::clang::CFG*> > + : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { + + typedef ::clang::CFG::const_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(); } +}; +} // end llvm namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h new file mode 100644 index 0000000..3c76201 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -0,0 +1,320 @@ +//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- 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 skeleton code for implementing dataflow analyses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER +#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER + +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Analysis/FlowSensitive/DataflowValues.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "functional" // STL + +namespace clang { + +//===----------------------------------------------------------------------===// +/// DataflowWorkListTy - Data structure representing the worklist used for +/// dataflow algorithms. +//===----------------------------------------------------------------------===// + +class DataflowWorkListTy { + llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet; + llvm::SmallVector<const CFGBlock *, 10> BlockQueue; +public: + /// enqueue - Add a block to the worklist. Blocks already on the + /// worklist are not added a second time. + void enqueue(const CFGBlock* B) { + unsigned char &x = BlockSet[B]; + if (x == 1) + return; + x = 1; + BlockQueue.push_back(B); + } + + /// dequeue - Remove a block from the worklist. + const CFGBlock* dequeue() { + assert(!BlockQueue.empty()); + const CFGBlock *B = BlockQueue.back(); + BlockQueue.pop_back(); + BlockSet[B] = 0; + return B; + } + + /// isEmpty - Return true if the worklist is empty. + bool isEmpty() const { return BlockQueue.empty(); } +}; + +//===----------------------------------------------------------------------===// +// BlockItrTraits - Traits classes that allow transparent iteration +// over successors/predecessors of a block depending on the direction +// of our dataflow analysis. +//===----------------------------------------------------------------------===// + +namespace dataflow { +template<typename Tag> struct ItrTraits {}; + +template <> struct ItrTraits<forward_analysis_tag> { + typedef CFGBlock::const_pred_iterator PrevBItr; + typedef CFGBlock::const_succ_iterator NextBItr; + typedef CFGBlock::const_iterator StmtItr; + + static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); } + static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); } + + static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); } + static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); } + + static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); } + static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); } + + static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) { + return BlockEdge(Prev, B, 0); + } + + static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) { + return BlockEdge(B, Next, 0); + } +}; + +template <> struct ItrTraits<backward_analysis_tag> { + typedef CFGBlock::const_succ_iterator PrevBItr; + typedef CFGBlock::const_pred_iterator NextBItr; + typedef CFGBlock::const_reverse_iterator StmtItr; + + static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); } + static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); } + + static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); } + static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); } + + static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); } + static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); } + + static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) { + return BlockEdge(B, Prev, 0); + } + + static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) { + return BlockEdge(Next, B, 0); + } +}; +} // end namespace dataflow + +//===----------------------------------------------------------------------===// +/// DataflowSolverTy - Generic dataflow solver. +//===----------------------------------------------------------------------===// + +template <typename _DFValuesTy, // Usually a subclass of DataflowValues + typename _TransferFuncsTy, + typename _MergeOperatorTy, + typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> > +class DataflowSolver { + + //===----------------------------------------------------===// + // Type declarations. + //===----------------------------------------------------===// + +public: + typedef _DFValuesTy DFValuesTy; + typedef _TransferFuncsTy TransferFuncsTy; + typedef _MergeOperatorTy MergeOperatorTy; + + typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag; + typedef typename _DFValuesTy::ValTy ValTy; + typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy; + typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy; + + typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits; + typedef typename ItrTraits::NextBItr NextBItr; + typedef typename ItrTraits::PrevBItr PrevBItr; + typedef typename ItrTraits::StmtItr StmtItr; + + //===----------------------------------------------------===// + // External interface: constructing and running the solver. + //===----------------------------------------------------===// + +public: + DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {} + ~DataflowSolver() {} + + /// runOnCFG - Computes dataflow values for all blocks in a CFG. + void runOnCFG(CFG& cfg, bool recordStmtValues = false) { + // Set initial dataflow values and boundary conditions. + D.InitializeValues(cfg); + // Solve the dataflow equations. This will populate D.EdgeDataMap + // with dataflow values. + SolveDataflowEquations(cfg, recordStmtValues); + } + + /// runOnBlock - Computes dataflow values for a given block. This + /// should usually be invoked only after previously computing + /// dataflow values using runOnCFG, as runOnBlock is intended to + /// only be used for querying the dataflow values within a block + /// with and Observer object. + void runOnBlock(const CFGBlock* B, bool recordStmtValues) { + BlockDataMapTy& M = D.getBlockDataMap(); + typename BlockDataMapTy::iterator I = M.find(B); + + if (I != M.end()) { + TF.getVal().copyValues(I->second); + ProcessBlock(B, recordStmtValues, AnalysisDirTag()); + } + } + + void runOnBlock(const CFGBlock& B, bool recordStmtValues) { + runOnBlock(&B, recordStmtValues); + } + void runOnBlock(CFG::iterator& I, bool recordStmtValues) { + runOnBlock(*I, recordStmtValues); + } + void runOnBlock(CFG::const_iterator& I, bool recordStmtValues) { + runOnBlock(*I, recordStmtValues); + } + + void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) { + for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) + runOnBlock(I, recordStmtValues); + } + + //===----------------------------------------------------===// + // Internal solver logic. + //===----------------------------------------------------===// + +private: + + /// SolveDataflowEquations - Perform the actual worklist algorithm + /// to compute dataflow values. + void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) { + EnqueueBlocksOnWorklist(cfg, AnalysisDirTag()); + + while (!WorkList.isEmpty()) { + const CFGBlock* B = WorkList.dequeue(); + ProcessMerge(cfg, B); + ProcessBlock(B, recordStmtValues, AnalysisDirTag()); + UpdateEdges(cfg, B, TF.getVal()); + } + } + + void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) { + // Enqueue all blocks to ensure the dataflow values are computed + // for every block. Not all blocks are guaranteed to reach the exit block. + for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) + WorkList.enqueue(&**I); + } + + void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) { + // Enqueue all blocks to ensure the dataflow values are computed + // for every block. Not all blocks are guaranteed to reach the exit block. + // Enqueue in reverse order since that will more likely match with + // the order they should ideally processed by the dataflow algorithm. + for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I) + WorkList.enqueue(&**I); + } + + void ProcessMerge(CFG& cfg, const CFGBlock* B) { + ValTy& V = TF.getVal(); + TF.SetTopValue(V); + + // Merge dataflow values from all predecessors of this block. + MergeOperatorTy Merge; + + EdgeDataMapTy& M = D.getEdgeDataMap(); + bool firstMerge = true; + + for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){ + + CFGBlock *PrevBlk = *I; + + if (!PrevBlk) + continue; + + typename EdgeDataMapTy::iterator EI = + M.find(ItrTraits::PrevEdge(B, PrevBlk)); + + if (EI != M.end()) { + if (firstMerge) { + firstMerge = false; + V.copyValues(EI->second); + } + else + Merge(V, EI->second); + } + } + + // Set the data for the block. + D.getBlockDataMap()[B].copyValues(V); + } + + /// ProcessBlock - Process the transfer functions for a given block. + void ProcessBlock(const CFGBlock* B, bool recordStmtValues, + dataflow::forward_analysis_tag) { + + for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) + ProcessStmt(*I, recordStmtValues, AnalysisDirTag()); + + TF.VisitTerminator(const_cast<CFGBlock*>(B)); + } + + void ProcessBlock(const CFGBlock* B, bool recordStmtValues, + dataflow::backward_analysis_tag) { + + TF.VisitTerminator(const_cast<CFGBlock*>(B)); + + for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) + ProcessStmt(*I, recordStmtValues, AnalysisDirTag()); + } + + void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) { + if (record) D.getStmtDataMap()[S] = TF.getVal(); + TF.BlockStmt_Visit(const_cast<Stmt*>(S)); + } + + void ProcessStmt(const Stmt* S, bool record, dataflow::backward_analysis_tag){ + TF.BlockStmt_Visit(const_cast<Stmt*>(S)); + if (record) D.getStmtDataMap()[S] = TF.getVal(); + } + + /// UpdateEdges - After processing the transfer functions for a + /// block, update the dataflow value associated with the block's + /// outgoing/incoming edges (depending on whether we do a + // forward/backward analysis respectively) + void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) { + for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I) + if (CFGBlock *NextBlk = *I) + UpdateEdgeValue(ItrTraits::NextEdge(B, NextBlk),V, NextBlk); + } + + /// UpdateEdgeValue - Update the value associated with a given edge. + void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) { + EdgeDataMapTy& M = D.getEdgeDataMap(); + typename EdgeDataMapTy::iterator I = M.find(E); + + if (I == M.end()) { // First computed value for this edge? + M[E].copyValues(V); + WorkList.enqueue(TargetBlock); + } + else if (!_Equal()(V,I->second)) { + I->second.copyValues(V); + WorkList.enqueue(TargetBlock); + } + } + +private: + DFValuesTy& D; + DataflowWorkListTy WorkList; + TransferFuncsTy TF; +}; + +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h new file mode 100644 index 0000000..7aa15c5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h @@ -0,0 +1,172 @@ +//===--- DataflowValues.h - Data structure for dataflow values --*- 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 skeleton data structure for encapsulating the dataflow +// values for a CFG. Typically this is subclassed to provide methods for +// computing these values from a CFG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_VALUES +#define LLVM_CLANG_ANALYSES_DATAFLOW_VALUES + +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/ProgramPoint.h" +#include "llvm/ADT/DenseMap.h" + +//===----------------------------------------------------------------------===// +/// Dataflow Directional Tag Classes. These are used for tag dispatching +/// within the dataflow solver/transfer functions to determine what direction +/// a dataflow analysis flows. +//===----------------------------------------------------------------------===// + +namespace clang { +namespace dataflow { + struct forward_analysis_tag {}; + struct backward_analysis_tag {}; +} // end namespace dataflow + +//===----------------------------------------------------------------------===// +/// DataflowValues. Container class to store dataflow values for a CFG. +//===----------------------------------------------------------------------===// + +template <typename ValueTypes, + typename _AnalysisDirTag = dataflow::forward_analysis_tag > +class DataflowValues { + + //===--------------------------------------------------------------------===// + // Type declarations. + //===--------------------------------------------------------------------===// + +public: + typedef typename ValueTypes::ValTy ValTy; + typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy; + typedef _AnalysisDirTag AnalysisDirTag; + typedef llvm::DenseMap<ProgramPoint, ValTy> EdgeDataMapTy; + typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy; + typedef llvm::DenseMap<const Stmt*, ValTy> StmtDataMapTy; + + //===--------------------------------------------------------------------===// + // Predicates. + //===--------------------------------------------------------------------===// + +public: + /// isForwardAnalysis - Returns true if the dataflow values are computed + /// from a forward analysis. + bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); } + + /// isBackwardAnalysis - Returns true if the dataflow values are computed + /// from a backward analysis. + bool isBackwardAnalysis() { return !isForwardAnalysis(); } + +private: + bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; } + bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; } + + //===--------------------------------------------------------------------===// + // Initialization and accessors methods. + //===--------------------------------------------------------------------===// + +public: + DataflowValues() : StmtDataMap(NULL) {} + ~DataflowValues() { delete StmtDataMap; } + + /// InitializeValues - Invoked by the solver to initialize state needed for + /// dataflow analysis. This method is usually specialized by subclasses. + void InitializeValues(const CFG& cfg) {} + + + /// getEdgeData - Retrieves the dataflow values associated with a + /// CFG edge. + ValTy& getEdgeData(const BlockEdge& E) { + typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E); + assert (I != EdgeDataMap.end() && "No data associated with Edge."); + return I->second; + } + + const ValTy& getEdgeData(const BlockEdge& E) const { + return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E); + } + + /// getBlockData - Retrieves the dataflow values associated with a + /// specified CFGBlock. If the dataflow analysis is a forward analysis, + /// this data is associated with the END of the block. If the analysis + /// is a backwards analysis, it is associated with the ENTRY of the block. + ValTy& getBlockData(const CFGBlock* B) { + typename BlockDataMapTy::iterator I = BlockDataMap.find(B); + assert (I != BlockDataMap.end() && "No data associated with block."); + return I->second; + } + + const ValTy& getBlockData(const CFGBlock* B) const { + return const_cast<DataflowValues*>(this)->getBlockData(B); + } + + /// getStmtData - Retrieves the dataflow values associated with a + /// specified Stmt. If the dataflow analysis is a forward analysis, + /// this data corresponds to the point immediately before a Stmt. + /// If the analysis is a backwards analysis, it is associated with + /// the point after a Stmt. This data is only computed for block-level + /// expressions, and only when requested when the analysis is executed. + ValTy& getStmtData(const Stmt* S) { + assert (StmtDataMap && "Dataflow values were not computed for statements."); + typename StmtDataMapTy::iterator I = StmtDataMap->find(S); + assert (I != StmtDataMap->end() && "No data associated with statement."); + return I->second; + } + + const ValTy& getStmtData(const Stmt* S) const { + return const_cast<DataflowValues*>(this)->getStmtData(S); + } + + /// getEdgeDataMap - Retrieves the internal map between CFG edges and + /// dataflow values. Usually used by a dataflow solver to compute + /// values for blocks. + EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; } + const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; } + + /// getBlockDataMap - Retrieves the internal map between CFGBlocks and + /// dataflow values. If the dataflow analysis operates in the forward + /// direction, the values correspond to the dataflow values at the start + /// of the block. Otherwise, for a backward analysis, the values correpsond + /// to the dataflow values at the end of the block. + BlockDataMapTy& getBlockDataMap() { return BlockDataMap; } + const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; } + + /// getStmtDataMap - Retrieves the internal map between Stmts and + /// dataflow values. + StmtDataMapTy& getStmtDataMap() { + if (!StmtDataMap) StmtDataMap = new StmtDataMapTy(); + return *StmtDataMap; + } + + const StmtDataMapTy& getStmtDataMap() const { + return const_cast<DataflowValues*>(this)->getStmtDataMap(); + } + + /// getAnalysisData - Retrieves the meta data associated with a + /// dataflow analysis for analyzing a particular CFG. + /// This is typically consumed by transfer function code (via the solver). + /// This can also be used by subclasses to interpret the dataflow values. + AnalysisDataTy& getAnalysisData() { return AnalysisData; } + const AnalysisDataTy& getAnalysisData() const { return AnalysisData; } + + //===--------------------------------------------------------------------===// + // Internal data. + //===--------------------------------------------------------------------===// + +protected: + EdgeDataMapTy EdgeDataMap; + BlockDataMapTy BlockDataMap; + StmtDataMapTy* StmtDataMap; + AnalysisDataTy AnalysisData; +}; + +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h new file mode 100644 index 0000000..075838d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h @@ -0,0 +1,380 @@ +//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- 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 interface ProgramPoint, which identifies a +// distinct location in a function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT +#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT + +#include "clang/Analysis/CFG.h" +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <utility> + +namespace clang { + +class LocationContext; +class FunctionDecl; + +class ProgramPoint { +public: + enum Kind { BlockEdgeKind, + BlockEntranceKind, + BlockExitKind, + PreStmtKind, + PostStmtKind, + PreLoadKind, + PostLoadKind, + PreStoreKind, + PostStoreKind, + PostPurgeDeadSymbolsKind, + PostStmtCustomKind, + PostLValueKind, + CallEnterKind, + CallExitKind, + MinPostStmtKind = PostStmtKind, + MaxPostStmtKind = PostLValueKind }; + +private: + std::pair<const void *, const void *> Data; + Kind K; + + // The LocationContext could be NULL to allow ProgramPoint to be used in + // context insensitive analysis. + const LocationContext *L; + const void *Tag; + +protected: + ProgramPoint(const void* P, Kind k, const LocationContext *l, + const void *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, + const void *tag = 0) + : Data(P1, P2), K(k), L(l), Tag(tag) {} + +protected: + const void* getData1() const { return Data.first; } + const void* getData2() const { return Data.second; } + const void *getTag() const { return Tag; } + +public: + Kind getKind() const { return K; } + + const LocationContext *getLocationContext() const { return L; } + + // For use with DenseMap. This hash is probably slow. + unsigned getHashValue() const { + llvm::FoldingSetNodeID ID; + Profile(ID); + return ID.ComputeHash(); + } + + 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; + } + + bool operator!=(const ProgramPoint& RHS) const { + return K != RHS.K || Data != RHS.Data || 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.AddPointer(Tag); + } +}; + +class BlockEntrance : public ProgramPoint { +public: + BlockEntrance(const CFGBlock* B, const LocationContext *L, + const void *tag = 0) + : ProgramPoint(B, BlockEntranceKind, L, tag) {} + + CFGBlock* getBlock() const { + return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); + } + + CFGElement getFirstElement() const { + const CFGBlock* B = getBlock(); + return B->empty() ? CFGElement() : B->front(); + } + + Stmt *getFirstStmt() const { + return getFirstElement().getStmt(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockEntranceKind; + } +}; + +class BlockExit : public ProgramPoint { +public: + BlockExit(const CFGBlock* B, const LocationContext *L) + : ProgramPoint(B, BlockExitKind, L) {} + + CFGBlock* getBlock() const { + return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); + } + + Stmt* getLastStmt() const { + const CFGBlock* B = getBlock(); + return B->empty() ? CFGElement() : B->back(); + } + + Stmt* getTerminator() const { + return getBlock()->getTerminator(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockExitKind; + } +}; + +class StmtPoint : public ProgramPoint { +public: + StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, + const void *tag) + : ProgramPoint(S, p2, k, L, tag) {} + + const Stmt *getStmt() const { return (const Stmt*) getData1(); } + + template <typename T> + const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } + + static bool classof(const ProgramPoint* Location) { + unsigned k = Location->getKind(); + return k >= PreStmtKind && k <= MaxPostStmtKind; + } +}; + + +class PreStmt : public StmtPoint { +public: + PreStmt(const Stmt *S, const LocationContext *L, const void *tag, + const Stmt *SubStmt = 0) + : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} + + const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PreStmtKind; + } +}; + +class PostStmt : public StmtPoint { +protected: + PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0) + : StmtPoint(S, NULL, k, L, tag) {} + + PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L, + const void *tag =0) + : StmtPoint(S, data, k, L, tag) {} + +public: + explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0) + : StmtPoint(S, NULL, PostStmtKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + unsigned k = Location->getKind(); + return k >= MinPostStmtKind && k <= MaxPostStmtKind; + } +}; + +class PostStmtCustom : public PostStmt { +public: + PostStmtCustom(const Stmt* S, + const std::pair<const void*, const void*>* TaggedData,\ + const LocationContext *L) + : PostStmt(S, TaggedData, PostStmtCustomKind, L) {} + + const std::pair<const void*, const void*>& getTaggedPair() const { + return + *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2()); + } + + const void* getTag() const { return getTaggedPair().first; } + + const void* getTaggedData() const { return getTaggedPair().second; } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStmtCustomKind; + } +}; + + +class LocationCheck : public StmtPoint { +protected: + LocationCheck(const Stmt *S, const LocationContext *L, + ProgramPoint::Kind K, const void *tag) + : StmtPoint(S, NULL, K, L, tag) {} + + static bool classof(const ProgramPoint *location) { + unsigned k = location->getKind(); + return k == PreLoadKind || k == PreStoreKind; + } +}; + +class PreLoad : public LocationCheck { +public: + PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0) + : LocationCheck(S, L, PreLoadKind, tag) {} + + static bool classof(const ProgramPoint *location) { + return location->getKind() == PreLoadKind; + } +}; + +class PreStore : public LocationCheck { +public: + PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0) + : LocationCheck(S, L, PreStoreKind, tag) {} + + static bool classof(const ProgramPoint *location) { + return location->getKind() == PreStoreKind; + } +}; + +class PostLoad : public PostStmt { +public: + PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostLoadKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostLoadKind; + } +}; + +class PostStore : public PostStmt { +public: + PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostStoreKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStoreKind; + } +}; + +class PostLValue : public PostStmt { +public: + PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostLValueKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostLValueKind; + } +}; + +class PostPurgeDeadSymbols : public PostStmt { +public: + PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostPurgeDeadSymbolsKind; + } +}; + +class BlockEdge : public ProgramPoint { +public: + BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L) + : ProgramPoint(B1, B2, BlockEdgeKind, L) {} + + CFGBlock* getSrc() const { + return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1())); + } + + CFGBlock* getDst() const { + return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2())); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockEdgeKind; + } +}; + +class CallEnter : public StmtPoint { +public: + // CallEnter uses the caller's location context. + CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L) + : StmtPoint(S, fd, CallEnterKind, L, 0) {} + + const Stmt *getCallExpr() const { + return static_cast<const Stmt *>(getData1()); + } + + const FunctionDecl *getCallee() const { + return static_cast<const FunctionDecl *>(getData2()); + } + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallEnterKind; + } +}; + +class CallExit : public StmtPoint { +public: + // CallExit uses the callee's location context. + CallExit(const Stmt *S, const LocationContext *L) + : StmtPoint(S, 0, CallExitKind, L, 0) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallExitKind; + } +}; + + +} // end namespace clang + + +namespace llvm { // Traits specialization for DenseMap + +template <> struct DenseMapInfo<clang::ProgramPoint> { + +static inline clang::ProgramPoint getEmptyKey() { + uintptr_t x = + reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); +} + +static inline clang::ProgramPoint getTombstoneKey() { + uintptr_t x = + reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); +} + +static unsigned getHashValue(const clang::ProgramPoint& Loc) { + return Loc.getHashValue(); +} + +static bool isEqual(const clang::ProgramPoint& L, + const clang::ProgramPoint& R) { + return L == R; +} + +}; + +template <> +struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h new file mode 100644 index 0000000..27ecc66 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h @@ -0,0 +1,307 @@ +// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- 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 definition of dataflow types used by analyses such +// as LiveVariables and UninitializedValues. The underlying dataflow values +// are implemented as bitvectors, but the definitions in this file include +// the necessary boilerplate to use with our dataflow framework. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STMTDECLBVDVAL_H +#define LLVM_CLANG_STMTDECLBVDVAL_H + +#include "clang/Analysis/CFG.h" +#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { + + class Stmt; + class ASTContext; + +struct DeclBitVector_Types { + + class Idx { + unsigned I; + public: + explicit Idx(unsigned i) : I(i) {} + Idx() : I(~0U) {} + + bool isValid() const { + return I != ~0U; + } + operator unsigned() const { + assert (isValid()); + return I; + } + }; + + //===--------------------------------------------------------------------===// + // AnalysisDataTy - Whole-function meta data. + //===--------------------------------------------------------------------===// + + class AnalysisDataTy { + public: + typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy; + typedef DMapTy::const_iterator decl_iterator; + + protected: + DMapTy DMap; + unsigned NDecls; + + public: + + AnalysisDataTy() : NDecls(0) {} + virtual ~AnalysisDataTy() {} + + bool isTracked(const NamedDecl* SD) { return DMap.find(SD) != DMap.end(); } + + Idx getIdx(const NamedDecl* SD) const { + DMapTy::const_iterator I = DMap.find(SD); + return I == DMap.end() ? Idx() : Idx(I->second); + } + + unsigned getNumDecls() const { return NDecls; } + + void Register(const NamedDecl* SD) { + if (!isTracked(SD)) DMap[SD] = NDecls++; + } + + decl_iterator begin_decl() const { return DMap.begin(); } + decl_iterator end_decl() const { return DMap.end(); } + }; + + //===--------------------------------------------------------------------===// + // ValTy - Dataflow value. + //===--------------------------------------------------------------------===// + + class ValTy { + llvm::BitVector DeclBV; + public: + + void resetDeclValues(AnalysisDataTy& AD) { + DeclBV.resize(AD.getNumDecls()); + DeclBV.reset(); + } + + void setDeclValues(AnalysisDataTy& AD) { + DeclBV.resize(AD.getNumDecls()); + DeclBV.set(); + } + + void resetValues(AnalysisDataTy& AD) { + resetDeclValues(AD); + } + + bool operator==(const ValTy& RHS) const { + assert (sizesEqual(RHS)); + return DeclBV == RHS.DeclBV; + } + + void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; } + + llvm::BitVector::reference getBit(unsigned i) { + return DeclBV[i]; + } + + bool getBit(unsigned i) const { + return DeclBV[i]; + } + + llvm::BitVector::reference + operator()(const NamedDecl* ND, const AnalysisDataTy& AD) { + return getBit(AD.getIdx(ND)); + } + + bool operator()(const NamedDecl* ND, const AnalysisDataTy& AD) const { + return getBit(AD.getIdx(ND)); + } + + llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; } + const llvm::BitVector::reference getDeclBit(unsigned i) const { + return const_cast<llvm::BitVector&>(DeclBV)[i]; + } + + ValTy& operator|=(const ValTy& RHS) { + assert (sizesEqual(RHS)); + DeclBV |= RHS.DeclBV; + return *this; + } + + ValTy& operator&=(const ValTy& RHS) { + assert (sizesEqual(RHS)); + DeclBV &= RHS.DeclBV; + return *this; + } + + ValTy& OrDeclBits(const ValTy& RHS) { + return operator|=(RHS); + } + + ValTy& AndDeclBits(const ValTy& RHS) { + return operator&=(RHS); + } + + bool sizesEqual(const ValTy& RHS) const { + return DeclBV.size() == RHS.DeclBV.size(); + } + }; + + //===--------------------------------------------------------------------===// + // Some useful merge operations. + //===--------------------------------------------------------------------===// + + struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } }; + struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } }; +}; + + +struct StmtDeclBitVector_Types { + + //===--------------------------------------------------------------------===// + // AnalysisDataTy - Whole-function meta data. + //===--------------------------------------------------------------------===// + + class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy { + ASTContext* ctx; + CFG* cfg; + public: + AnalysisDataTy() : ctx(0), cfg(0) {} + virtual ~AnalysisDataTy() {} + + void setContext(ASTContext& c) { ctx = &c; } + ASTContext& getContext() { + assert(ctx && "ASTContext should not be NULL."); + return *ctx; + } + + void setCFG(CFG& c) { cfg = &c; } + CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; } + + bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); } + using DeclBitVector_Types::AnalysisDataTy::isTracked; + + unsigned getIdx(const Stmt* S) const { + CFG::BlkExprNumTy I = cfg->getBlkExprNum(S); + assert(I && "Stmtession not tracked for bitvector."); + return I; + } + using DeclBitVector_Types::AnalysisDataTy::getIdx; + + unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); } + }; + + //===--------------------------------------------------------------------===// + // ValTy - Dataflow value. + //===--------------------------------------------------------------------===// + + class ValTy : public DeclBitVector_Types::ValTy { + llvm::BitVector BlkExprBV; + typedef DeclBitVector_Types::ValTy ParentTy; + + static inline ParentTy& ParentRef(ValTy& X) { + return static_cast<ParentTy&>(X); + } + + static inline const ParentTy& ParentRef(const ValTy& X) { + return static_cast<const ParentTy&>(X); + } + + public: + + void resetBlkExprValues(AnalysisDataTy& AD) { + BlkExprBV.resize(AD.getNumBlkExprs()); + BlkExprBV.reset(); + } + + void setBlkExprValues(AnalysisDataTy& AD) { + BlkExprBV.resize(AD.getNumBlkExprs()); + BlkExprBV.set(); + } + + void resetValues(AnalysisDataTy& AD) { + resetDeclValues(AD); + resetBlkExprValues(AD); + } + + void setValues(AnalysisDataTy& AD) { + setDeclValues(AD); + setBlkExprValues(AD); + } + + bool operator==(const ValTy& RHS) const { + return ParentRef(*this) == ParentRef(RHS) + && BlkExprBV == RHS.BlkExprBV; + } + + void copyValues(const ValTy& RHS) { + ParentRef(*this).copyValues(ParentRef(RHS)); + BlkExprBV = RHS.BlkExprBV; + } + + llvm::BitVector::reference + operator()(const Stmt* S, const AnalysisDataTy& AD) { + return BlkExprBV[AD.getIdx(S)]; + } + const llvm::BitVector::reference + operator()(const Stmt* S, const AnalysisDataTy& AD) const { + return const_cast<ValTy&>(*this)(S,AD); + } + + using DeclBitVector_Types::ValTy::operator(); + + + llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; } + const llvm::BitVector::reference getStmtBit(unsigned i) const { + return const_cast<llvm::BitVector&>(BlkExprBV)[i]; + } + + ValTy& OrBlkExprBits(const ValTy& RHS) { + BlkExprBV |= RHS.BlkExprBV; + return *this; + } + + ValTy& AndBlkExprBits(const ValTy& RHS) { + BlkExprBV &= RHS.BlkExprBV; + return *this; + } + + ValTy& operator|=(const ValTy& RHS) { + assert (sizesEqual(RHS)); + ParentRef(*this) |= ParentRef(RHS); + BlkExprBV |= RHS.BlkExprBV; + return *this; + } + + ValTy& operator&=(const ValTy& RHS) { + assert (sizesEqual(RHS)); + ParentRef(*this) &= ParentRef(RHS); + BlkExprBV &= RHS.BlkExprBV; + return *this; + } + + bool sizesEqual(const ValTy& RHS) const { + return ParentRef(*this).sizesEqual(ParentRef(RHS)) + && BlkExprBV.size() == RHS.BlkExprBV.size(); + } + }; + + //===--------------------------------------------------------------------===// + // Some useful merge operations. + //===--------------------------------------------------------------------===// + + struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } }; + struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } }; + +}; +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h new file mode 100644 index 0000000..c6c9eed --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h @@ -0,0 +1,216 @@ +//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- 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 BumpVector, a vector-like ADT whose contents are +// allocated from a BumpPtrAllocator. +// +//===----------------------------------------------------------------------===// + +// FIXME: Most of this is copy-and-paste from SmallVector.h. We can +// refactor this core logic into something common that is shared between +// the two. The main thing that is different is the allocation strategy. + +#ifndef LLVM_CLANG_BUMP_VECTOR +#define LLVM_CLANG_BUMP_VECTOR + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/PointerIntPair.h" +#include <algorithm> +#include <cstring> + +namespace clang { + +class BumpVectorContext { + llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc; +public: + /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator + /// and destroys it when the BumpVectorContext object is destroyed. + BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {} + + /// Construct a new BumpVectorContext that reuses an existing + /// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the + /// BumpVectorContext object is destroyed. + BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {} + + ~BumpVectorContext() { + if (Alloc.getInt()) + delete Alloc.getPointer(); + } + + llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); } +}; + +template<typename T> +class BumpVector { + T *Begin, *End, *Capacity; +public: + // Default ctor - Initialize to empty. + explicit BumpVector(BumpVectorContext &C, unsigned N) + : Begin(NULL), End(NULL), Capacity(NULL) { + reserve(C, N); + } + + ~BumpVector() { + if (llvm::is_class<T>::value) { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + } + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return 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());} + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + + reference operator[](unsigned idx) { + assert(Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert(Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + if (llvm::is_class<T>::value) { + destroy_range(Begin, End); + } + End = Begin; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + void push_back(const_reference Elt, BumpVectorContext &C) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(C); + goto Retry; + } + + void reserve(BumpVectorContext &C, unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(C, N); + } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return Capacity - Begin; } + +private: + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(BumpVectorContext &C, size_type MinSize = 1); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + + // Allocate the memory from the BumpPtrAllocator. + T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity); + + // Copy the elements over. + if (llvm::is_class<T>::value) { + std::uninitialized_copy(Begin, End, NewElts); + // Destroy the original elements. + destroy_range(Begin, End); + } + else { + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + } + + // For now, leak 'Begin'. We can add it back to a freelist in + // BumpVectorContext. + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +} // end: clang namespace +#endif // end: LLVM_CLANG_BUMP_VECTOR diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h new file mode 100644 index 0000000..f720639 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h @@ -0,0 +1,47 @@ +//===-- 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 new file mode 100644 index 0000000..d627b88 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -0,0 +1,92 @@ +//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- 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 template class CFGRecStmtDeclVisitor, which extends +// CFGRecStmtVisitor by implementing (typed) visitation of decls. +// +// FIXME: This may not be fully complete. We currently explore only subtypes +// of ScopedDecl. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H +#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H + +#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" + +#define DISPATCH_CASE(CASE,CLASS) \ +case Decl::CASE: \ +static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<CLASS*>(D));\ +break; + +#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS(CLASS* D) {} +#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS(CLASS* D)\ + { static_cast<ImplClass*>(this)->VisitVarDecl(D); } + + +namespace clang { +template <typename ImplClass> +class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> { +public: + + void VisitDeclRefExpr(DeclRefExpr* DR) { + static_cast<ImplClass*>(this)->VisitDecl(DR->getDecl()); + } + + void VisitDeclStmt(DeclStmt* DS) { + for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); + DI != DE; ++DI) { + Decl* D = *DI; + static_cast<ImplClass*>(this)->VisitDecl(D); + // Visit the initializer. + if (VarDecl* VD = dyn_cast<VarDecl>(D)) + if (Expr* I = VD->getInit()) + static_cast<ImplClass*>(this)->Visit(I); + } + } + + void VisitDecl(Decl* D) { + switch (D->getKind()) { + DISPATCH_CASE(Function,FunctionDecl) + DISPATCH_CASE(CXXMethod,CXXMethodDecl) + DISPATCH_CASE(Var,VarDecl) + DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) + DISPATCH_CASE(ImplicitParam,ImplicitParamDecl) + DISPATCH_CASE(EnumConstant,EnumConstantDecl) + DISPATCH_CASE(Typedef,TypedefDecl) + DISPATCH_CASE(Record,RecordDecl) // FIXME: Refine. VisitStructDecl? + DISPATCH_CASE(Enum,EnumDecl) + default: + assert(false && "Subtype of ScopedDecl not handled."); + } + } + + DEFAULT_DISPATCH(VarDecl) + DEFAULT_DISPATCH(FunctionDecl) + DEFAULT_DISPATCH(CXXMethodDecl) + DEFAULT_DISPATCH_VARDECL(ParmVarDecl) + DEFAULT_DISPATCH(ImplicitParamDecl) + DEFAULT_DISPATCH(EnumConstantDecl) + DEFAULT_DISPATCH(TypedefDecl) + DEFAULT_DISPATCH(RecordDecl) + DEFAULT_DISPATCH(EnumDecl) + DEFAULT_DISPATCH(ObjCInterfaceDecl) + DEFAULT_DISPATCH(ObjCClassDecl) + DEFAULT_DISPATCH(ObjCMethodDecl) + DEFAULT_DISPATCH(ObjCProtocolDecl) + DEFAULT_DISPATCH(ObjCCategoryDecl) +}; + +} // end namespace clang + +#undef DISPATCH_CASE +#undef DEFAULT_DISPATCH +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h new file mode 100644 index 0000000..75a4ac6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h @@ -0,0 +1,54 @@ +//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- 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 template class CFGRecStmtVisitor, which extends +// CFGStmtVisitor by implementing a default recursive visit of all statements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H +#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H + +#include "clang/Analysis/Visitors/CFGStmtVisitor.h" + +namespace clang { +template <typename ImplClass> +class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> { +public: + + void VisitStmt(Stmt* S) { + static_cast< ImplClass* >(this)->VisitChildren(S); + } + + void VisitConditionVariableInit(Stmt *S) { + assert(S == this->getCurrentBlkStmt()); + VarDecl *CondVar = 0; + switch (S->getStmtClass()) { +#define CONDVAR_CASE(CLASS) \ +case Stmt::CLASS ## Class:\ +CondVar = cast<CLASS>(S)->getConditionVariable();\ +break; + CONDVAR_CASE(IfStmt) + CONDVAR_CASE(ForStmt) + CONDVAR_CASE(SwitchStmt) + CONDVAR_CASE(WhileStmt) +#undef CONDVAR_CASE + default: + assert(false && "Infeasible"); + } + static_cast<ImplClass*>(this)->Visit(CondVar->getInit()); + } + + // Defining operator() allows the visitor to be used as a C++ style functor. + void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);} +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h new file mode 100644 index 0000000..8a85ec1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -0,0 +1,168 @@ +//===--- CFGStmtVisitor.h - Visitor for Stmts in a 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 defines the CFGStmtVisitor interface, which extends +// StmtVisitor. This interface is useful for visiting statements in a CFG +// where some statements have implicit control-flow and thus should +// be treated specially. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H +#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H + +#include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/CFG.h" + +namespace clang { + +#define DISPATCH_CASE(CLASS) \ +case Stmt::CLASS ## Class: return \ +static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S)); + +#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\ +{ return\ + static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\ + cast<Expr>(S)); } + +template <typename ImplClass, typename RetTy=void> +class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> { + Stmt* CurrentBlkStmt; + + struct NullifyStmt { + Stmt*& S; + + NullifyStmt(Stmt*& s) : S(s) {} + ~NullifyStmt() { S = NULL; } + }; + +public: + CFGStmtVisitor() : CurrentBlkStmt(NULL) {} + + Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; } + + RetTy Visit(Stmt* S) { + if (S == CurrentBlkStmt || + !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S)) + return StmtVisitor<ImplClass,RetTy>::Visit(S); + else + return RetTy(); + } + + /// VisitConditionVariableInit - Handle the initialization of condition + /// variables at branches. Valid statements include IfStmt, ForStmt, + /// WhileStmt, and SwitchStmt. + RetTy VisitConditionVariableInit(Stmt *S) { + return RetTy(); + } + + /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in + /// CFGBlocks. Root statements are the statements that appear explicitly in + /// the list of statements in a CFGBlock. For substatements, or when there + /// is no implementation provided for a BlockStmt_XXX method, we default + /// to using StmtVisitor's Visit method. + RetTy BlockStmt_Visit(Stmt* S) { + CurrentBlkStmt = S; + NullifyStmt cleanup(CurrentBlkStmt); + + switch (S->getStmtClass()) { + case Stmt::IfStmtClass: + case Stmt::ForStmtClass: + case Stmt::WhileStmtClass: + case Stmt::SwitchStmtClass: + return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S); + + DISPATCH_CASE(StmtExpr) + DISPATCH_CASE(ConditionalOperator) + DISPATCH_CASE(ObjCForCollectionStmt) + + case Stmt::BinaryOperatorClass: { + BinaryOperator* B = cast<BinaryOperator>(S); + if (B->isLogicalOp()) + return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B); + else if (B->getOpcode() == BinaryOperator::Comma) + return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B); + // Fall through. + } + + default: + if (isa<Expr>(S)) + return + static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S)); + else + return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); + } + } + + DEFAULT_BLOCKSTMT_VISIT(StmtExpr) + DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator) + + RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { + return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); + } + + RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { + return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E); + } + + RetTy BlockStmt_VisitExpr(Expr* E) { + return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E); + } + + RetTy BlockStmt_VisitStmt(Stmt* S) { + return static_cast<ImplClass*>(this)->Visit(S); + } + + RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) { + return + static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B); + } + + RetTy BlockStmt_VisitComma(BinaryOperator* B) { + return + static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B); + } + + //===--------------------------------------------------------------------===// + // Utility methods. Not called by default (but subclasses may use them). + //===--------------------------------------------------------------------===// + + /// VisitChildren: Call "Visit" on each child of S. + void VisitChildren(Stmt* S) { + + switch (S->getStmtClass()) { + default: + break; + + case Stmt::StmtExprClass: { + CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt(); + if (CS->body_empty()) return; + static_cast<ImplClass*>(this)->Visit(CS->body_back()); + return; + } + + case Stmt::BinaryOperatorClass: { + BinaryOperator* B = cast<BinaryOperator>(S); + if (B->getOpcode() != BinaryOperator::Comma) break; + static_cast<ImplClass*>(this)->Visit(B->getRHS()); + return; + } + } + + for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I) + if (*I) static_cast<ImplClass*>(this)->Visit(*I); + } +}; + +#undef DEFAULT_BLOCKSTMT_VISIT +#undef DISPATCH_CASE + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def new file mode 100644 index 0000000..b306954 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def @@ -0,0 +1,562 @@ +//===--- Builtins.def - Builtin function info 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 standard builtin function database. Users of this file +// must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// FIXME: This should really be a .td file, but that requires modifying tblgen. +// Perhaps tblgen should have plugins. + +// The first value provided to the macro specifies the function name of the +// builtin, and results in a clang::builtin::BIXX enum value for XX. + +// The second value provided to the macro specifies the type of the function +// (result value, then each argument) as follows: +// v -> void +// b -> boolean +// c -> char +// s -> short +// i -> int +// f -> float +// d -> double +// z -> size_t +// F -> constant CFString +// a -> __builtin_va_list +// A -> "reference" to __builtin_va_list +// V -> Vector, following num elements and a base type. +// X -> _Complex, followed by the base type. +// P -> FILE +// J -> jmp_buf +// SJ -> sigjmp_buf +// . -> "...". This may only occur at the end of the function list. +// +// Types maybe prefixed with the following modifiers: +// L -> long (e.g. Li for 'long int') +// LL -> long long +// LLL -> __int128_t (e.g. LLLi) +// S -> signed +// U -> unsigned +// +// Types may be postfixed with the following modifiers: +// * -> pointer (optionally followed by an address space number) +// & -> reference (optionally followed by an address space number) +// C -> const +// D -> volatile + +// The third value provided to the macro specifies information about attributes +// of the function. These must be kept in sync with the predicates in the +// Builtin::Context class. Currently we have: +// n -> nothrow +// r -> noreturn +// c -> const +// F -> this is a libc/libm function with a '__builtin_' prefix added. +// f -> this is a libc/libm function without the '__builtin_' prefix. It can +// be followed by ':headername:' to state which header this function +// comes from. +// p:N: -> this is a printf-like function whose Nth argument is the format +// string. +// P:N: -> similar to the p:N: attribute, but the function is like vprintf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// e -> const, but only when -fmath-errno=0 +// FIXME: gcc has nonnull + +#if defined(BUILTIN) && !defined(LIBBUILTIN) +# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) BUILTIN(ID, TYPE, ATTRS) +#endif + +// Standard libc/libm functions: +BUILTIN(__builtin_atan2 , "ddd" , "Fnc") +BUILTIN(__builtin_atan2f, "fff" , "Fnc") +BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc") +BUILTIN(__builtin_abs , "ii" , "ncF") +BUILTIN(__builtin_copysign, "ddd", "ncF") +BUILTIN(__builtin_copysignf, "fff", "ncF") +BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") +BUILTIN(__builtin_fabs , "dd" , "ncF") +BUILTIN(__builtin_fabsf, "ff" , "ncF") +BUILTIN(__builtin_fabsl, "LdLd", "ncF") +BUILTIN(__builtin_fmod , "ddd" , "Fnc") +BUILTIN(__builtin_fmodf, "fff" , "Fnc") +BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc") +BUILTIN(__builtin_frexp , "ddi*" , "Fnc") +BUILTIN(__builtin_frexpf, "ffi*" , "Fnc") +BUILTIN(__builtin_frexpl, "LdLdi*", "Fnc") +BUILTIN(__builtin_huge_val, "d", "nc") +BUILTIN(__builtin_huge_valf, "f", "nc") +BUILTIN(__builtin_huge_vall, "Ld", "nc") +BUILTIN(__builtin_inf , "d" , "nc") +BUILTIN(__builtin_inff , "f" , "nc") +BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_ldexp , "ddi" , "Fnc") +BUILTIN(__builtin_ldexpf, "ffi" , "Fnc") +BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc") +BUILTIN(__builtin_modf , "ddd*" , "Fnc") +BUILTIN(__builtin_modff, "fff*" , "Fnc") +BUILTIN(__builtin_modfl, "LdLdLd*", "Fnc") +BUILTIN(__builtin_nan, "dcC*" , "ncF") +BUILTIN(__builtin_nanf, "fcC*" , "ncF") +BUILTIN(__builtin_nanl, "LdcC*", "ncF") +BUILTIN(__builtin_nans, "dcC*" , "ncF") +BUILTIN(__builtin_nansf, "fcC*" , "ncF") +BUILTIN(__builtin_nansl, "LdcC*", "ncF") +BUILTIN(__builtin_powi , "ddi" , "Fnc") +BUILTIN(__builtin_powif, "ffi" , "Fnc") +BUILTIN(__builtin_powil, "LdLdi", "Fnc") +BUILTIN(__builtin_pow , "ddd" , "Fnc") +BUILTIN(__builtin_powf, "fff" , "Fnc") +BUILTIN(__builtin_powl, "LdLdLd", "Fnc") + +// Standard unary libc/libm functions with double/float/long double variants: +BUILTIN(__builtin_acos , "dd" , "Fnc") +BUILTIN(__builtin_acosf, "ff" , "Fnc") +BUILTIN(__builtin_acosl, "LdLd", "Fnc") +BUILTIN(__builtin_asin , "dd" , "Fnc") +BUILTIN(__builtin_asinf, "ff" , "Fnc") +BUILTIN(__builtin_asinl, "LdLd", "Fnc") +BUILTIN(__builtin_atan , "dd" , "Fnc") +BUILTIN(__builtin_atanf, "ff" , "Fnc") +BUILTIN(__builtin_atanl, "LdLd", "Fnc") +BUILTIN(__builtin_ceil , "dd" , "Fnc") +BUILTIN(__builtin_ceilf, "ff" , "Fnc") +BUILTIN(__builtin_ceill, "LdLd", "Fnc") +BUILTIN(__builtin_cos , "dd" , "Fnc") +BUILTIN(__builtin_cosf, "ff" , "Fnc") +BUILTIN(__builtin_cosh , "dd" , "Fnc") +BUILTIN(__builtin_coshf, "ff" , "Fnc") +BUILTIN(__builtin_coshl, "LdLd", "Fnc") +BUILTIN(__builtin_cosl, "LdLd", "Fnc") +BUILTIN(__builtin_exp , "dd" , "Fnc") +BUILTIN(__builtin_expf, "ff" , "Fnc") +BUILTIN(__builtin_expl, "LdLd", "Fnc") +BUILTIN(__builtin_floor , "dd" , "Fnc") +BUILTIN(__builtin_floorf, "ff" , "Fnc") +BUILTIN(__builtin_floorl, "LdLd", "Fnc") +BUILTIN(__builtin_hypot , "ddd" , "Fnc") +BUILTIN(__builtin_hypotf, "fff" , "Fnc") +BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc") +BUILTIN(__builtin_log , "dd" , "Fnc") +BUILTIN(__builtin_log10 , "dd" , "Fnc") +BUILTIN(__builtin_log10f, "ff" , "Fnc") +BUILTIN(__builtin_log10l, "LdLd", "Fnc") +BUILTIN(__builtin_logf, "ff" , "Fnc") +BUILTIN(__builtin_logl, "LdLd", "Fnc") +BUILTIN(__builtin_sin , "dd" , "Fnc") +BUILTIN(__builtin_sinf, "ff" , "Fnc") +BUILTIN(__builtin_sinh , "dd" , "Fnc") +BUILTIN(__builtin_sinhf, "ff" , "Fnc") +BUILTIN(__builtin_sinhl, "LdLd", "Fnc") +BUILTIN(__builtin_sinl, "LdLd", "Fnc") +BUILTIN(__builtin_sqrt , "dd" , "Fnc") +BUILTIN(__builtin_sqrtf, "ff" , "Fnc") +BUILTIN(__builtin_sqrtl, "LdLd", "Fnc") +BUILTIN(__builtin_tan , "dd" , "Fnc") +BUILTIN(__builtin_tanf, "ff" , "Fnc") +BUILTIN(__builtin_tanh , "dd" , "Fnc") +BUILTIN(__builtin_tanhf, "ff" , "Fnc") +BUILTIN(__builtin_tanhl, "LdLd", "Fnc") +BUILTIN(__builtin_tanl, "LdLd", "Fnc") + +// C99 complex builtins +BUILTIN(__builtin_cabs, "dXd", "Fnc") +BUILTIN(__builtin_cabsf, "fXf", "Fnc") +BUILTIN(__builtin_cabsl, "LdXLd", "Fnc") +BUILTIN(__builtin_cacos, "XdXd", "Fnc") +BUILTIN(__builtin_cacosf, "XfXf", "Fnc") +BUILTIN(__builtin_cacosl, "XLdXLd", "Fnc") +BUILTIN(__builtin_carg, "dXd", "Fnc") +BUILTIN(__builtin_cargf, "fXf", "Fnc") +BUILTIN(__builtin_cargl, "LdXLd", "Fnc") +BUILTIN(__builtin_casin, "XdXd", "Fnc") +BUILTIN(__builtin_casinf, "XfXf", "Fnc") +BUILTIN(__builtin_casinl, "XLdXLd", "Fnc") +BUILTIN(__builtin_catan, "XdXd", "Fnc") +BUILTIN(__builtin_catanf, "XfXf", "Fnc") +BUILTIN(__builtin_catanl, "XLdXLd", "Fnc") +BUILTIN(__builtin_ccos, "XdXd", "Fnc") +BUILTIN(__builtin_ccosf, "XfXf", "Fnc") +BUILTIN(__builtin_ccosl, "XLdXLd", "Fnc") +BUILTIN(__builtin_ccosh, "XdXd", "Fnc") +BUILTIN(__builtin_ccoshf, "XfXf", "Fnc") +BUILTIN(__builtin_ccoshl, "XLdXLd", "Fnc") +BUILTIN(__builtin_cexp, "XdXd", "Fnc") +BUILTIN(__builtin_cexpf, "XfXf", "Fnc") +BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc") +BUILTIN(__builtin_cimag, "dXd", "Fnc") +BUILTIN(__builtin_cimagf, "fXf", "Fnc") +BUILTIN(__builtin_cimagl, "LdXLd", "Fnc") +BUILTIN(__builtin_conj, "dXd", "Fnc") +BUILTIN(__builtin_conjf, "fXf", "Fnc") +BUILTIN(__builtin_conjl, "LdXLd", "Fnc") +BUILTIN(__builtin_clog, "XdXd", "Fnc") +BUILTIN(__builtin_clogf, "XfXf", "Fnc") +BUILTIN(__builtin_clogl, "XLdXLd", "Fnc") +BUILTIN(__builtin_cproj, "XdXd", "Fnc") +BUILTIN(__builtin_cprojf, "XfXf", "Fnc") +BUILTIN(__builtin_cprojl, "XLdXLd", "Fnc") +BUILTIN(__builtin_cpow, "XdXdXd", "Fnc") +BUILTIN(__builtin_cpowf, "XfXfXf", "Fnc") +BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fnc") +BUILTIN(__builtin_creal, "dXd", "Fnc") +BUILTIN(__builtin_crealf, "fXf", "Fnc") +BUILTIN(__builtin_creall, "LdXLd", "Fnc") +BUILTIN(__builtin_csin, "XdXd", "Fnc") +BUILTIN(__builtin_csinf, "XfXf", "Fnc") +BUILTIN(__builtin_csinl, "XLdXLd", "Fnc") +BUILTIN(__builtin_csinh, "XdXd", "Fnc") +BUILTIN(__builtin_csinhf, "XfXf", "Fnc") +BUILTIN(__builtin_csinhl, "XLdXLd", "Fnc") +BUILTIN(__builtin_csqrt, "XdXd", "Fnc") +BUILTIN(__builtin_csqrtf, "XfXf", "Fnc") +BUILTIN(__builtin_csqrtl, "XLdXLd", "Fnc") +BUILTIN(__builtin_ctan, "XdXd", "Fnc") +BUILTIN(__builtin_ctanf, "XfXf", "Fnc") +BUILTIN(__builtin_ctanl, "XLdXLd", "Fnc") +BUILTIN(__builtin_ctanh, "XdXd", "Fnc") +BUILTIN(__builtin_ctanhf, "XfXf", "Fnc") +BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc") + +// FP Comparisons. +BUILTIN(__builtin_isgreater , "i.", "nc") +BUILTIN(__builtin_isgreaterequal, "i.", "nc") +BUILTIN(__builtin_isless , "i.", "nc") +BUILTIN(__builtin_islessequal , "i.", "nc") +BUILTIN(__builtin_islessgreater , "i.", "nc") +BUILTIN(__builtin_isunordered , "i.", "nc") + +// Unary FP classification +BUILTIN(__builtin_fpclassify, "iiiii.", "nc") +BUILTIN(__builtin_isfinite, "i.", "nc") +BUILTIN(__builtin_isinf, "i.", "nc") +BUILTIN(__builtin_isinf_sign, "i.", "nc") +BUILTIN(__builtin_isnan, "i.", "nc") +BUILTIN(__builtin_isnormal, "i.", "nc") + +// FP signbit builtins +BUILTIN(__builtin_signbit, "id", "nc") +BUILTIN(__builtin_signbitf, "if", "nc") +BUILTIN(__builtin_signbitl, "iLd", "nc") + +// Builtins for arithmetic. +BUILTIN(__builtin_clz , "iUi" , "nc") +BUILTIN(__builtin_clzl , "iULi" , "nc") +BUILTIN(__builtin_clzll, "iULLi", "nc") +// TODO: int clzimax(uintmax_t) +BUILTIN(__builtin_ctz , "iUi" , "nc") +BUILTIN(__builtin_ctzl , "iULi" , "nc") +BUILTIN(__builtin_ctzll, "iULLi", "nc") +// TODO: int ctzimax(uintmax_t) +BUILTIN(__builtin_ffs , "iUi" , "nc") +BUILTIN(__builtin_ffsl , "iULi" , "nc") +BUILTIN(__builtin_ffsll, "iULLi", "nc") +BUILTIN(__builtin_parity , "iUi" , "nc") +BUILTIN(__builtin_parityl , "iULi" , "nc") +BUILTIN(__builtin_parityll, "iULLi", "nc") +BUILTIN(__builtin_popcount , "iUi" , "nc") +BUILTIN(__builtin_popcountl , "iULi" , "nc") +BUILTIN(__builtin_popcountll, "iULLi", "nc") + +// FIXME: These type signatures are not correct for targets with int != 32-bits +// or with ULL != 64-bits. +BUILTIN(__builtin_bswap32, "UiUi", "nc") +BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") + +// Random GCC builtins +BUILTIN(__builtin_constant_p, "Us.", "nc") +BUILTIN(__builtin_classify_type, "i.", "nc") +BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") +BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc") +BUILTIN(__builtin_va_start, "vA.", "n") +BUILTIN(__builtin_va_end, "vA", "n") +BUILTIN(__builtin_va_copy, "vAA", "n") +BUILTIN(__builtin_stdarg_start, "vA.", "n") +BUILTIN(__builtin_bcmp, "iv*v*z", "n") +BUILTIN(__builtin_bcopy, "vv*v*z", "n") +BUILTIN(__builtin_bzero, "vv*z", "nF") +BUILTIN(__builtin_memchr, "v*vC*iz", "nF") +BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") +BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") +BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") +BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") +BUILTIN(__builtin_memset, "v*v*iz", "nF") +BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF") +BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") +BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF") +BUILTIN(__builtin_strcat, "c*c*cC*", "nF") +BUILTIN(__builtin_strchr, "c*cC*i", "nF") +BUILTIN(__builtin_strcmp, "icC*cC*", "nF") +BUILTIN(__builtin_strcpy, "c*c*cC*", "nF") +BUILTIN(__builtin_strcspn, "zcC*cC*", "nF") +BUILTIN(__builtin_strdup, "c*cC*", "nF") +BUILTIN(__builtin_strlen, "zcC*", "nF") +BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF") +BUILTIN(__builtin_strncat, "c*c*cC*z", "nF") +BUILTIN(__builtin_strncmp, "icC*cC*z", "nF") +BUILTIN(__builtin_strncpy, "c*c*cC*z", "nF") +BUILTIN(__builtin_strndup, "c*cC*z", "nF") +BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF") +BUILTIN(__builtin_strrchr, "c*cC*i", "nF") +BUILTIN(__builtin_strspn, "zcC*cC*", "nF") +BUILTIN(__builtin_strstr, "c*cC*cC*", "nF") +BUILTIN(__builtin_return_address, "v*Ui", "n") +BUILTIN(__builtin_extract_return_addr, "v*v*", "n") +BUILTIN(__builtin_frame_address, "v*Ui", "n") +BUILTIN(__builtin_flt_rounds, "i", "nc") +BUILTIN(__builtin_setjmp, "iv**", "") +BUILTIN(__builtin_longjmp, "vv**i", "r") +BUILTIN(__builtin_unwind_init, "v", "") +BUILTIN(__builtin_eh_return_data_regno, "ii", "nc") +BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") +BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") + +// GCC exception builtins +BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t! +BUILTIN(__builtin_frob_return_addr, "v*v*", "n") +BUILTIN(__builtin_dwarf_cfa, "v*", "n") +BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") +BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") +BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t + +// GCC Object size checking builtins +BUILTIN(__builtin_object_size, "zv*i", "n") +BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "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___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") +BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:") +BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:") +BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:") +BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "FP:3:") +BUILTIN(__builtin___fprintf_chk, "iP*icC*.", "Fp:2:") +BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:") +BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:") +BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") + +BUILTIN(__builtin_expect, "LiLiLi" , "nc") +BUILTIN(__builtin_prefetch, "vvC*.", "nc") +BUILTIN(__builtin_trap, "v", "nr") +BUILTIN(__builtin_unreachable, "v", "nr") +BUILTIN(__builtin_shufflevector, "v." , "nc") +BUILTIN(__builtin_alloca, "v*z" , "n") + +// "Overloaded" Atomic operator builtins. These are overloaded to support data +// types of i8, i16, i32, i64, and i128. The front-end sees calls to the +// non-suffixed version of these (which has a bogus type) and transforms them to +// the right overloaded version in Sema (plus casts). + +// FIXME: These assume that char -> i8, short -> i16, int -> i32, +// long long -> i64. + +BUILTIN(__sync_fetch_and_add, "v.", "") +BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_sub, "v.", "") +BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_or, "v.", "") +BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_and, "v.", "") +BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_fetch_and_xor, "v.", "") +BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n") +BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n") +BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n") +BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") + + +BUILTIN(__sync_add_and_fetch, "v.", "") +BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_sub_and_fetch, "v.", "") +BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_or_and_fetch, "v.", "") +BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_and_and_fetch, "v.", "") +BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_xor_and_fetch, "v.", "") +BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n") +BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n") +BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n") +BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_bool_compare_and_swap, "v.", "") +BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n") +BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n") +BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "n") +BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "n") +BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "n") + +BUILTIN(__sync_val_compare_and_swap, "v.", "") +BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "n") +BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "n") +BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "n") +BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n") +BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n") + +BUILTIN(__sync_lock_test_and_set, "v.", "") +BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n") +BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n") +BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n") +BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n") +BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n") + +BUILTIN(__sync_lock_release, "v.", "") +BUILTIN(__sync_lock_release_1, "vc*.", "n") +BUILTIN(__sync_lock_release_2, "vs*.", "n") +BUILTIN(__sync_lock_release_4, "vi*.", "n") +BUILTIN(__sync_lock_release_8, "vLLi*.", "n") +BUILTIN(__sync_lock_release_16, "vLLLi*.", "n") + + + +// Non-overloaded atomic builtins. +BUILTIN(__sync_synchronize, "v.", "n") +// LLVM instruction builtin [Clang extension]. +BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n") +// GCC does not support these, they are a Clang extension. +BUILTIN(__sync_fetch_and_min, "ii*i", "n") +BUILTIN(__sync_fetch_and_max, "ii*i", "n") +BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n") +BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") + +// Random libc builtins. +BUILTIN(__builtin_abort, "v", "Fnr") +BUILTIN(__builtin_index, "c*cC*i", "Fn") +BUILTIN(__builtin_rindex, "c*cC*i", "Fn") + + + +// C99 library functions +// C99 stdlib.h +LIBBUILTIN(abort, "v", "fr", "stdlib.h") +LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h") +LIBBUILTIN(exit, "vi", "fr", "stdlib.h") +LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h") +LIBBUILTIN(malloc, "v*z", "f", "stdlib.h") +LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h") +// C99 string.h +LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h") +LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h") +LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h") +LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h") +LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h") +LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h") +LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h") +LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h") +LIBBUILTIN(strchr, "c*cC*i", "f", "string.h") +LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h") +LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h") +LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h") +LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h") +LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h") +LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h") +LIBBUILTIN(memset, "v*v*iz", "f", "string.h") +LIBBUILTIN(strerror, "c*i", "f", "string.h") +LIBBUILTIN(strlen, "zcC*", "f", "string.h") +// C99 stdio.h +LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h") +LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h") +LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h") +LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h") +LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h") +LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h") +LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h") +LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h") +// C99 +LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h") + +// Non-C library functions +// FIXME: Non-C-standard stuff shouldn't be builtins in non-GNU mode! +LIBBUILTIN(alloca, "v*z", "f", "stdlib.h") +// POSIX string.h +LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h") +LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h") +LIBBUILTIN(strdup, "c*cC*", "f", "string.h") +LIBBUILTIN(strndup, "c*cC*z", "f", "string.h") +// POSIX strings.h +LIBBUILTIN(index, "c*cC*i", "f", "strings.h") +LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h") +LIBBUILTIN(bzero, "vv*z", "f", "strings.h") +// POSIX unistd.h +LIBBUILTIN(_exit, "vi", "fr", "unistd.h") +// POSIX setjmp.h +LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h") +LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h") + +// FIXME: This type isn't very correct, it should be +// id objc_msgSend(id, SEL) +// but we need new type letters for that. +LIBBUILTIN(objc_msgSend, "v*.", "f", "objc/message.h") + +// Builtin math library functions +LIBBUILTIN(pow, "ddd", "fe", "math.h") +LIBBUILTIN(powl, "LdLdLd", "fe", "math.h") +LIBBUILTIN(powf, "fff", "fe", "math.h") + +LIBBUILTIN(sqrt, "dd", "fe", "math.h") +LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h") +LIBBUILTIN(sqrtf, "ff", "fe", "math.h") + +LIBBUILTIN(sin, "dd", "fe", "math.h") +LIBBUILTIN(sinl, "LdLd", "fe", "math.h") +LIBBUILTIN(sinf, "ff", "fe", "math.h") + +LIBBUILTIN(cos, "dd", "fe", "math.h") +LIBBUILTIN(cosl, "LdLd", "fe", "math.h") +LIBBUILTIN(cosf, "ff", "fe", "math.h") + +#undef BUILTIN +#undef LIBBUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h new file mode 100644 index 0000000..07f091a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h @@ -0,0 +1,142 @@ +//===--- Builtins.h - Builtin function header -------------------*- 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 enum values for all the target-independent builtin +// functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_BUILTINS_H +#define LLVM_CLANG_BASIC_BUILTINS_H + +#include <cstring> + +// VC++ defines 'alloca' as an object-like macro, which interferes with our +// builtins. +#undef alloca + +namespace llvm { + template <typename T> class SmallVectorImpl; +} + +namespace clang { + class TargetInfo; + class IdentifierTable; + class ASTContext; + class QualType; + +namespace Builtin { +enum ID { + NotBuiltin = 0, // This is not a builtin function. +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/Builtins.def" + FirstTSBuiltin +}; + +struct Info { + const char *Name, *Type, *Attributes, *HeaderName; + bool Suppressed; + + bool operator==(const Info &RHS) const { + return !strcmp(Name, RHS.Name) && + !strcmp(Type, RHS.Type) && + !strcmp(Attributes, RHS.Attributes); + } + bool operator!=(const Info &RHS) const { return !(*this == RHS); } +}; + +/// Builtin::Context - This holds information about target-independent and +/// target-specific builtins, allowing easy queries by clients. +class Context { + const Info *TSRecords; + unsigned NumTSRecords; +public: + Context(const TargetInfo &Target); + + /// InitializeBuiltins - Mark the identifiers for all the builtins with their + /// appropriate builtin ID # and mark any non-portable builtin identifiers as + /// such. + void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false); + + /// \brief Popular the vector with the names of all of the builtins. + void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names, + bool NoBuiltins); + + /// Builtin::GetName - Return the identifier name for the specified builtin, + /// e.g. "__builtin_abs". + const char *GetName(unsigned ID) const { + return GetRecord(ID).Name; + } + + /// GetTypeString - Get the type descriptor string for the specified builtin. + const char *GetTypeString(unsigned ID) const { + return GetRecord(ID).Type; + } + + /// isConst - Return true if this function has no side effects and doesn't + /// read memory. + bool isConst(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'c') != 0; + } + + /// isNoThrow - Return true if we know this builtin never throws an exception. + bool isNoThrow(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'n') != 0; + } + + /// isNoReturn - Return true if we know this builtin never returns. + bool isNoReturn(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'r') != 0; + } + + /// isLibFunction - Return true if this is a builtin for a libc/libm function, + /// with a "__builtin_" prefix (e.g. __builtin_abs). + bool isLibFunction(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'F') != 0; + } + + /// \brief Determines whether this builtin is a predefined libc/libm + /// function, such as "malloc", where we know the signature a + /// priori. + bool isPredefinedLibFunction(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'f') != 0; + } + + /// \brief If this is a library function that comes from a specific + /// header, retrieve that header name. + const char *getHeaderName(unsigned ID) const { + return GetRecord(ID).HeaderName; + } + + /// \brief Determine whether this builtin is like printf in its + /// formatting rules and, if so, set the index to the format string + /// argument and whether this function as a va_list argument. + bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); + + /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list + /// as an operand or return type. + bool hasVAListUse(unsigned ID) const { + return strpbrk(GetRecord(ID).Type, "Aa") != 0; + } + + /// isConstWithoutErrno - Return true if this function has no side + /// effects and doesn't read memory, except for possibly errno. Such + /// functions can be const when the MathErrno lang option is + /// disabled. + bool isConstWithoutErrno(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 'e') != 0; + } + +private: + const Info &GetRecord(unsigned ID) const; +}; + +} +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def new file mode 100644 index 0000000..4973076a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def @@ -0,0 +1,20 @@ +//===--- BuiltinsARM.def - ARM 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 ARM-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +// FIXME: This is just a placeholder. NEON intrinsics should be listed here. +BUILTIN(__builtin_thread_pointer, "v*", "") + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def new file mode 100644 index 0000000..287bba9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def @@ -0,0 +1,114 @@ +//===--- BuiltinsPPC.def - PowerPC 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 PowerPC-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// FIXME: this needs to be the full list supported by GCC. Right now, I'm just +// adding stuff on demand. + +// The format of this database matches clang/Basic/Builtins.def. + +// This is just a placeholder, the types and attributes are wrong. +BUILTIN(__builtin_altivec_abs_v16qi, "V16UcV16Sc", "") +BUILTIN(__builtin_altivec_abs_v8hi, "V8UsV8Ss", "") +BUILTIN(__builtin_altivec_abs_v4si, "V4UiV4Si", "") + +BUILTIN(__builtin_altivec_abss_v16qi, "V16UcV16Sc", "") +BUILTIN(__builtin_altivec_abss_v8hi, "V8UsV8Ss", "") +BUILTIN(__builtin_altivec_abss_v4si, "V4UiV4Si", "") + +BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vaddubs, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vavgsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_stvx, "vV4iiv*", "") +BUILTIN(__builtin_altivec_stvxl, "vV4iiv*", "") +BUILTIN(__builtin_altivec_stvebx, "vV16civ*", "") +BUILTIN(__builtin_altivec_stvehx, "vV8siv*", "") +BUILTIN(__builtin_altivec_stvewx, "vV4iiv*", "") + +BUILTIN(__builtin_altivec_vcmpbfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "") +BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "") +BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "") +BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "") +BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "") +BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vmaxub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "") + +BUILTIN(__builtin_altivec_mfvscr, "V8Us", "") + +BUILTIN(__builtin_altivec_vminsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vminub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "") + +BUILTIN(__builtin_altivec_mtvscr, "vV4i", "") + +BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "") +BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "") +BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "") +BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "") +BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "") + +// FIXME: Obviously incomplete. + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def new file mode 100644 index 0000000..a878dd1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def @@ -0,0 +1,328 @@ +//===--- BuiltinsX86.def - X86 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. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +// FIXME: In GCC, these builtins are defined depending on whether support for +// MMX/SSE/etc is turned on. We should do this too. + +// FIXME: Ideally we would be able to pull this information from what +// LLVM already knows about X86 builtins. We need to match the LLVM +// definition anyway, since code generation will lower to the +// intrinsic if one exists. + +BUILTIN(__builtin_ia32_emms , "v", "") + +// FIXME: Are these nothrow/const? + +// SSE intrinsics. +BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comile, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comige, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "") +BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "") +BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "") +BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "") +BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "") +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_minps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "") +BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "") +BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "") +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_pmulhuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "") +BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "") +BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "") +BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "") +BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "") +BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "") +BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") +BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "") +BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") +BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "") +BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "") +BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "") +BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "") +BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "") +BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "") +BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "") +BUILTIN(__builtin_ia32_stmxcsr, "Ui", "") +BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") +BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") +BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") +BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") +BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "") +BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") +BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") +BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") +BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") +BUILTIN(__builtin_ia32_movmskps, "iV4f", "") +BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "") +BUILTIN(__builtin_ia32_movntps, "vf*V4f", "") +BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "") +BUILTIN(__builtin_ia32_sfence, "v", "") +BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "") +BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "") +BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "") +BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "") +BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "") +BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "") +BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "") +BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "") +BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "") +BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "") +BUILTIN(__builtin_ia32_movmskpd, "iV2d", "") +BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "") +BUILTIN(__builtin_ia32_movnti, "vi*i", "") +BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "") +BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "") +BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "") +BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "") +BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "") +BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "") +BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "") +BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "") +BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "") +BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "") +BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "") +BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "") +BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "") +BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "") +BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "") +BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "") +BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "") +BUILTIN(__builtin_ia32_clflush, "vvC*", "") +BUILTIN(__builtin_ia32_lfence, "v", "") +BUILTIN(__builtin_ia32_mfence, "v", "") +BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "") +BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "") +BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "") +BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "") +BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "") +BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "") +BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "") +BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "") +BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "") +BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "") +BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "") +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_monitor, "vv*UiUi", "") +BUILTIN(__builtin_ia32_mwait, "vUiUi", "") +BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") +BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") +BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") +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_blendvpd, "V2dV2dV2dV2d", "") +BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "") + +BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "") +BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "") +BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "") +BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "") +BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "") +BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "") +BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "") +BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "") +BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "") +BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "") +BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "") +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", "") + +// 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_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", "") + +BUILTIN(__builtin_ia32_crc32qi, "iic", "") +BUILTIN(__builtin_ia32_crc32hi, "iis", "") +BUILTIN(__builtin_ia32_crc32si, "iii", "") +BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "") + +// AES +BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "") +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CMakeLists.txt b/contrib/llvm/tools/clang/include/clang/Basic/CMakeLists.txt new file mode 100644 index 0000000..c2a4e13 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/CMakeLists.txt @@ -0,0 +1,20 @@ +macro(clang_diag_gen component) + tablegen(Diagnostic${component}Kinds.inc + -gen-clang-diags-defs -clang-component=${component}) + add_custom_target(ClangDiagnostic${component} + DEPENDS Diagnostic${component}Kinds.inc) +endmacro(clang_diag_gen) + +set(LLVM_TARGET_DEFINITIONS Diagnostic.td) +clang_diag_gen(Analysis) +clang_diag_gen(AST) +clang_diag_gen(Common) +clang_diag_gen(Driver) +clang_diag_gen(Frontend) +clang_diag_gen(Lex) +clang_diag_gen(Parse) +clang_diag_gen(Sema) +tablegen(DiagnosticGroups.inc + -gen-clang-diag-groups) +add_custom_target(ClangDiagnosticGroups + DEPENDS DiagnosticGroups.inc) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h new file mode 100644 index 0000000..4da2ad75 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h @@ -0,0 +1,159 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long 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 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* 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); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); +#endif + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h new file mode 100644 index 0000000..62f06ed --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h @@ -0,0 +1,968 @@ +//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- 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 Diagnostic-related interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DIAGNOSTIC_H +#define LLVM_CLANG_DIAGNOSTIC_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/type_traits.h" +#include <string> +#include <vector> +#include <cassert> + +namespace llvm { + template <typename T> class SmallVectorImpl; + class raw_ostream; +} + +namespace clang { + class DeclContext; + class DiagnosticBuilder; + class DiagnosticClient; + class FileManager; + class IdentifierInfo; + class LangOptions; + class PartialDiagnostic; + class Preprocessor; + class SourceManager; + class SourceRange; + + // Import the diagnostic enums themselves. + namespace diag { + // Start position for diagnostics. + enum { + DIAG_START_DRIVER = 300, + DIAG_START_FRONTEND = DIAG_START_DRIVER + 100, + DIAG_START_LEX = DIAG_START_FRONTEND + 100, + 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 + 1500, + DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 + }; + + class CustomDiagInfo; + + /// diag::kind - All of the diagnostics that can be emitted by the frontend. + typedef unsigned kind; + + // Get typedefs for common diagnostics. + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#include "clang/Basic/DiagnosticCommonKinds.inc" + NUM_BUILTIN_COMMON_DIAGNOSTICS +#undef DIAG + }; + + /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs + /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR + /// (emit as an error). It allows clients to map errors to + /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this + /// one). + enum Mapping { + // NOTE: 0 means "uncomputed". + MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it. + MAP_WARNING = 2, //< Map this diagnostic to a warning. + MAP_ERROR = 3, //< Map this diagnostic to an error. + MAP_FATAL = 4, //< Map this diagnostic to a fatal error. + + /// Map this diagnostic to "warning", but make it immune to -Werror. This + /// happens when you specify -Wno-error=foo. + MAP_WARNING_NO_WERROR = 5, + /// Map this diagnostic to "error", but make it immune to -Wfatal-errors. + /// This happens for -Wno-fatal-errors=foo. + MAP_ERROR_NO_WFATAL = 6 + }; + } + +/// \brief Annotates a diagnostic with some code that should be +/// inserted, removed, or replaced to fix the problem. +/// +/// This kind of hint should be used when we are certain that the +/// introduction, removal, or modification of a particular (small!) +/// amount of code will correct a compilation error. The compiler +/// should also provide full recovery from such errors, such that +/// suppressing the diagnostic output can still result in successful +/// compilation. +class FixItHint { +public: + /// \brief Tokens that should be removed to correct the error. + SourceRange RemoveRange; + + /// \brief The location at which we should insert code to correct + /// the error. + SourceLocation InsertionLoc; + + /// \brief The actual code to insert at the insertion location, as a + /// string. + std::string CodeToInsert; + + /// \brief Empty code modification hint, indicating that no code + /// modification is known. + FixItHint() : RemoveRange(), InsertionLoc() { } + + bool isNull() const { + return !RemoveRange.isValid() && !InsertionLoc.isValid(); + } + + /// \brief Create a code modification hint that inserts the given + /// code string at a specific location. + static FixItHint CreateInsertion(SourceLocation InsertionLoc, + llvm::StringRef Code) { + FixItHint Hint; + Hint.InsertionLoc = InsertionLoc; + Hint.CodeToInsert = Code; + return Hint; + } + + /// \brief Create a code modification hint that removes the given + /// source range. + static FixItHint CreateRemoval(SourceRange RemoveRange) { + FixItHint Hint; + Hint.RemoveRange = RemoveRange; + return Hint; + } + + /// \brief Create a code modification hint that replaces the given + /// source range with the given code string. + static FixItHint CreateReplacement(SourceRange RemoveRange, + llvm::StringRef Code) { + FixItHint Hint; + Hint.RemoveRange = RemoveRange; + Hint.InsertionLoc = RemoveRange.getBegin(); + Hint.CodeToInsert = Code; + return Hint; + } +}; + +/// Diagnostic - This concrete class is used by the front-end to report +/// problems and issues. It massages the diagnostics (e.g. handling things like +/// "report warnings as errors" and passes them off to the DiagnosticClient for +/// reporting to the user. +class Diagnostic : public llvm::RefCountedBase<Diagnostic> { +public: + /// Level - The level of the diagnostic, after it has been through mapping. + enum Level { + Ignored, Note, Warning, Error, Fatal + }; + + /// ExtensionHandling - How do we handle otherwise-unmapped extension? This + /// is controlled by -pedantic and -pedantic-errors. + enum ExtensionHandling { + Ext_Ignore, Ext_Warn, Ext_Error + }; + + enum ArgumentKind { + ak_std_string, // std::string + ak_c_string, // const char * + ak_sint, // int + ak_uint, // unsigned + ak_identifierinfo, // IdentifierInfo + ak_qualtype, // QualType + ak_declarationname, // DeclarationName + ak_nameddecl, // NamedDecl * + ak_nestednamespec, // NestedNameSpecifier * + ak_declcontext // DeclContext * + }; + + /// ArgumentValue - This typedef represents on argument value, which is a + /// union discriminated by ArgumentKind, with a value. + typedef std::pair<ArgumentKind, intptr_t> ArgumentValue; + +private: + unsigned char AllExtensionsSilenced; // Used by __extension__ + bool IgnoreAllWarnings; // Ignore all warnings: -w + bool WarningsAsErrors; // Treat warnings like errors: + bool ErrorsAsFatal; // Treat errors like fatal errors. + bool SuppressSystemWarnings; // Suppress warnings in system headers. + bool SuppressAllDiagnostics; // Suppress all diagnostics. + unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. + unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, + // 0 -> no limit. + ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? + DiagnosticClient *Client; + + /// DiagMappings - Mapping information for diagnostics. Mapping info is + /// packed into four bits per diagnostic. The low three bits are the mapping + /// (an instance of diag::Mapping), or zero if unset. The high bit is set + /// when the mapping was established as a user mapping. If the high bit is + /// clear, then the low bits are set to the default value, and should be + /// mapped with -pedantic, -Werror, etc. + + typedef std::vector<unsigned char> DiagMappings; + mutable std::vector<DiagMappings> DiagMappingsStack; + + /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or + /// fatal error is emitted, and is sticky. + bool ErrorOccurred; + bool FatalErrorOccurred; + + /// LastDiagLevel - This is the level of the last diagnostic emitted. This is + /// used to emit continuation diagnostics with the same level as the + /// diagnostic that they follow. + Diagnostic::Level LastDiagLevel; + + unsigned NumWarnings; // Number of warnings reported + unsigned NumErrors; // Number of errors reported + unsigned NumErrorsSuppressed; // Number of errors suppressed + + /// CustomDiagInfo - Information for uniquing and looking up custom diags. + diag::CustomDiagInfo *CustomDiagInfo; + + /// ArgToStringFn - A function pointer that converts an opaque diagnostic + /// argument to a strings. This takes the modifiers and argument that was + /// present in the diagnostic. + /// + /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous + /// arguments formatted for this diagnostic. Implementations of this function + /// can use this information to avoid redundancy across arguments. + /// + /// This is a hack to avoid a layering violation between libbasic and libsema. + typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val, + const char *Modifier, unsigned ModifierLen, + const char *Argument, unsigned ArgumentLen, + const ArgumentValue *PrevArgs, + unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output, + void *Cookie); + void *ArgToStringCookie; + ArgToStringFnTy ArgToStringFn; + + /// \brief ID of the "delayed" diagnostic, which is a (typically + /// fatal) diagnostic that had to be delayed because it was found + /// while emitting another diagnostic. + unsigned DelayedDiagID; + + /// \brief First string argument for the delayed diagnostic. + std::string DelayedDiagArg1; + + /// \brief Second string argument for the delayed diagnostic. + std::string DelayedDiagArg2; + +public: + explicit Diagnostic(DiagnosticClient *client = 0); + ~Diagnostic(); + + //===--------------------------------------------------------------------===// + // Diagnostic characterization methods, used by a client to customize how + // + + DiagnosticClient *getClient() { return Client; } + const DiagnosticClient *getClient() const { return Client; } + + /// pushMappings - Copies the current DiagMappings and pushes the new copy + /// onto the top of the stack. + void pushMappings(); + + /// popMappings - Pops the current DiagMappings off the top of the stack + /// causing the new top of the stack to be the active mappings. Returns + /// true if the pop happens, false if there is only one DiagMapping on the + /// stack. + bool popMappings(); + + void setClient(DiagnosticClient* client) { Client = client; } + + /// setErrorLimit - Specify a limit for the number of errors we should + /// emit before giving up. Zero disables the limit. + void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } + + /// \brief Specify the maximum number of template instantiation + /// notes to emit along with a given diagnostic. + void setTemplateBacktraceLimit(unsigned Limit) { + TemplateBacktraceLimit = Limit; + } + + /// \brief Retrieve the maximum number of template instantiation + /// nodes to emit along with a given diagnostic. + unsigned getTemplateBacktraceLimit() const { + return TemplateBacktraceLimit; + } + + /// 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; } + bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; } + + /// setWarningsAsErrors - When set to true, any warnings reported are issued + /// as errors. + void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; } + bool getWarningsAsErrors() const { return WarningsAsErrors; } + + /// setErrorsAsFatal - When set to true, any error reported is made a + /// fatal error. + void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; } + bool getErrorsAsFatal() const { return ErrorsAsFatal; } + + /// setSuppressSystemWarnings - When set to true mask warnings that + /// come from system headers. + void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; } + bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; } + + /// \brief Suppress all diagnostics, to silence the front end when we + /// know that we don't want any more diagnostics to be passed along to the + /// client + void setSuppressAllDiagnostics(bool Val = true) { + SuppressAllDiagnostics = Val; + } + bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } + + /// \brief Pretend that the last diagnostic issued was ignored. This can + /// be used by clients who suppress diagnostics themselves. + void setLastDiagnosticIgnored() { + LastDiagLevel = Ignored; + } + + /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped + /// extension diagnostics are mapped onto ignore/warning/error. This + /// corresponds to the GCC -pedantic and -pedantic-errors option. + void setExtensionHandlingBehavior(ExtensionHandling H) { + ExtBehavior = H; + } + + /// AllExtensionsSilenced - This is a counter bumped when an __extension__ + /// block is encountered. When non-zero, all extension diagnostics are + /// entirely silenced, no matter how they are mapped. + void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } + void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } + bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } + + /// setDiagnosticMapping - This allows the client to specify that certain + /// warnings are ignored. Notes can never be mapped, errors can only be + /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. + void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) { + assert(Diag < diag::DIAG_UPPER_LIMIT && + "Can only map builtin diagnostics"); + assert((isBuiltinWarningOrExtension(Diag) || + (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && + "Cannot map errors into warnings!"); + setDiagnosticMappingInternal(Diag, Map, true); + } + + /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. + /// "unknown-pragmas" to have the specified mapping. This returns true and + /// ignores the request if "Group" was unknown, false otherwise. + bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map); + + bool hasErrorOccurred() const { return ErrorOccurred; } + bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } + + unsigned getNumErrors() const { return NumErrors; } + unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; } + unsigned getNumWarnings() const { return NumWarnings; } + + /// getCustomDiagID - Return an ID for a diagnostic with the specified message + /// and level. If this is the first request for this diagnosic, it is + /// registered and created, otherwise the existing ID is returned. + unsigned getCustomDiagID(Level L, llvm::StringRef Message); + + + /// ConvertArgToString - This method converts a diagnostic argument (as an + /// intptr_t) into the string that represents it. + void ConvertArgToString(ArgumentKind Kind, intptr_t Val, + const char *Modifier, unsigned ModLen, + const char *Argument, unsigned ArgLen, + const ArgumentValue *PrevArgs, unsigned NumPrevArgs, + llvm::SmallVectorImpl<char> &Output) const { + ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, + PrevArgs, NumPrevArgs, Output, ArgToStringCookie); + } + + void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { + ArgToStringFn = Fn; + ArgToStringCookie = Cookie; + } + + //===--------------------------------------------------------------------===// + // Diagnostic classification and reporting interfaces. + // + + /// getDescription - Given a diagnostic ID, return a description of the + /// issue. + const char *getDescription(unsigned DiagID) const; + + /// isNoteWarningOrExtension - Return true if the unmapped diagnostic + /// level of the specified diagnostic ID is a Warning or Extension. + /// This only works on builtin diagnostics, not custom ones, and is not legal to + /// call on NOTEs. + static bool isBuiltinWarningOrExtension(unsigned DiagID); + + /// \brief Determine whether the given built-in diagnostic ID is a + /// Note. + static bool isBuiltinNote(unsigned DiagID); + + /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic + /// ID is for an extension of some sort. + /// + static bool isBuiltinExtensionDiag(unsigned DiagID) { + bool ignored; + return isBuiltinExtensionDiag(DiagID, ignored); + } + + /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic + /// ID is for an extension of some sort. This also returns EnabledByDefault, + /// which is set to indicate whether the diagnostic is ignored by default (in + /// which case -pedantic enables it) or treated as a warning/error by default. + /// + static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); + + + /// getWarningOptionForDiag - Return the lowest-level warning option that + /// enables the specified diagnostic. If there is no -Wfoo flag that controls + /// the diagnostic, this returns null. + static const char *getWarningOptionForDiag(unsigned DiagID); + + /// getWarningOptionForDiag - Return the category number that a specified + /// DiagID belongs to, or 0 if no category. + static unsigned getCategoryNumberForDiag(unsigned DiagID); + + /// getCategoryNameFromID - Given a category ID, return the name of the + /// category. + static const char *getCategoryNameFromID(unsigned CategoryID); + + /// \brief Enumeration describing how the the emission of a diagnostic should + /// be treated when it occurs during C++ template argument deduction. + enum SFINAEResponse { + /// \brief The diagnostic should not be reported, but it should cause + /// template argument deduction to fail. + /// + /// The vast majority of errors that occur during template argument + /// deduction fall into this category. + SFINAE_SubstitutionFailure, + + /// \brief The diagnostic should be suppressed entirely. + /// + /// Warnings generally fall into this category. + SFINAE_Suppress, + + /// \brief The diagnostic should be reported. + /// + /// The diagnostic should be reported. Various fatal errors (e.g., + /// template instantiation depth exceeded) fall into this category. + SFINAE_Report + }; + + /// \brief Determines whether the given built-in diagnostic ID is + /// for an error that is suppressed if it occurs during C++ template + /// argument deduction. + /// + /// When an error is suppressed due to SFINAE, the template argument + /// deduction fails but no diagnostic is emitted. Certain classes of + /// errors, such as those errors that involve C++ access control, + /// are not SFINAE errors. + static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); + + /// getDiagnosticLevel - Based on the way the client configured the Diagnostic + /// object, classify the specified diagnostic ID into a Level, consumable by + /// the DiagnosticClient. + Level getDiagnosticLevel(unsigned DiagID) const; + + /// Report - Issue the message to the client. @c DiagID is a member of the + /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder + /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed. + /// @c Pos represents the source location associated with the diagnostic, + /// which can be an invalid location if no position information is available. + inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID); + inline DiagnosticBuilder Report(unsigned DiagID); + + /// \brief Determine whethere there is already a diagnostic in flight. + bool isDiagnosticInFlight() const { return CurDiagID != ~0U; } + + /// \brief Set the "delayed" diagnostic that will be emitted once + /// the current diagnostic completes. + /// + /// If a diagnostic is already in-flight but the front end must + /// report a problem (e.g., with an inconsistent file system + /// state), this routine sets a "delayed" diagnostic that will be + /// emitted after the current diagnostic completes. This should + /// only be used for fatal errors detected at inconvenient + /// times. If emitting a delayed diagnostic causes a second delayed + /// diagnostic to be introduced, that second delayed diagnostic + /// will be ignored. + /// + /// \param DiagID The ID of the diagnostic being delayed. + /// + /// \param Arg1 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// Diagnostic object itself. + /// + /// \param Arg2 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// Diagnostic object itself. + void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "", + llvm::StringRef Arg2 = ""); + + /// \brief Clear out the current diagnostic. + void Clear() { CurDiagID = ~0U; } + +private: + /// \brief Report the delayed diagnostic. + void ReportDelayed(); + + + /// getDiagnosticMappingInfo - Return the mapping info currently set for the + /// specified builtin diagnostic. This returns the high bit encoding, or zero + /// if the field is completely uninitialized. + diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const { + const DiagMappings ¤tMappings = DiagMappingsStack.back(); + return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15); + } + + void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map, + bool isUser) const { + if (isUser) Map |= 8; // Set the high bit for user mappings. + unsigned char &Slot = DiagMappingsStack.back()[DiagId/2]; + unsigned Shift = (DiagId & 1)*4; + Slot &= ~(15 << Shift); + Slot |= Map << Shift; + } + + /// getDiagnosticLevel - This is an internal implementation helper used when + /// DiagClass is already known. + Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const; + + // This is private state used by DiagnosticBuilder. We put it here instead of + // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight + // object. This implementation choice means that we can only have one + // diagnostic "in flight" at a time, but this seems to be a reasonable + // tradeoff to keep these objects small. Assertions verify that only one + // diagnostic is in flight at a time. + friend class DiagnosticBuilder; + friend class DiagnosticInfo; + + /// CurDiagLoc - This is the location of the current diagnostic that is in + /// flight. + FullSourceLoc CurDiagLoc; + + /// CurDiagID - This is the ID of the current diagnostic that is in flight. + /// This is set to ~0U when there is no diagnostic in flight. + unsigned CurDiagID; + + enum { + /// 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 + }; + + /// NumDiagArgs - This contains the number of entries in Arguments. + signed char NumDiagArgs; + /// NumRanges - 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]; + + /// DiagArgumentsStr - This holds the values of each string argument for the + /// current diagnostic. This value is only used when the corresponding + /// ArgumentKind is ak_std_string. + std::string DiagArgumentsStr[MaxArguments]; + + /// 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 intepretation depends on exactly what + /// 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. + SourceRange DiagRanges[10]; + + enum { MaxFixItHints = 3 }; + + /// FixItHints - If valid, provides a hint with some code + /// to insert, remove, or modify at a particular position. + FixItHint FixItHints[MaxFixItHints]; + + /// ProcessDiag - This is the method used to report a diagnostic that is + /// finally fully formed. + /// + /// \returns true if the diagnostic was emitted, false if it was + /// suppressed. + bool ProcessDiag(); +}; + +//===----------------------------------------------------------------------===// +// DiagnosticBuilder +//===----------------------------------------------------------------------===// + +/// DiagnosticBuilder - This is a little helper class used to produce +/// diagnostics. This is constructed by the Diagnostic::Report method, and +/// allows insertion of extra information (arguments and source ranges) into the +/// currently "in flight" diagnostic. When the temporary for the builder is +/// destroyed, the diagnostic is issued. +/// +/// Note that many of these will be created as temporary objects (many call +/// sites), so we want them to be small and we never want their address taken. +/// This ensures that compilers with somewhat reasonable optimizers will promote +/// the common fields to registers, eliminating increments of the NumArgs field, +/// for example. +class DiagnosticBuilder { + mutable Diagnostic *DiagObj; + mutable unsigned NumArgs, NumRanges, NumFixItHints; + + void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT + friend class Diagnostic; + explicit DiagnosticBuilder(Diagnostic *diagObj) + : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {} + +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; + } + + /// \brief Simple enumeration value used to give a name to the + /// suppress-diagnostic constructor. + enum SuppressKind { Suppress }; + + /// \brief Create an empty DiagnosticBuilder object that represents + /// no actual diagnostic. + explicit DiagnosticBuilder(SuppressKind) + : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { } + + /// \brief Force the diagnostic builder to emit the diagnostic now. + /// + /// Once this function has been called, the DiagnosticBuilder object + /// should not be used again before it is destroyed. + /// + /// \returns true if a diagnostic was emitted, false if the + /// diagnostic was suppressed. + bool Emit(); + + /// Destructor - The dtor emits the diagnostic if it hasn't already + /// been emitted. + ~DiagnosticBuilder() { Emit(); } + + /// isActive - Determine whether this diagnostic is still active. + bool isActive() const { return DiagObj != 0; } + + /// Operator bool: conversion of DiagnosticBuilder to bool always returns + /// true. This allows is to be used in boolean error contexts like: + /// return Diag(...); + operator bool() const { return true; } + + void AddString(llvm::StringRef S) const { + assert(NumArgs < Diagnostic::MaxArguments && + "Too many arguments to diagnostic!"); + if (DiagObj) { + DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string; + DiagObj->DiagArgumentsStr[NumArgs++] = S; + } + } + + void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { + assert(NumArgs < Diagnostic::MaxArguments && + "Too many arguments to diagnostic!"); + if (DiagObj) { + DiagObj->DiagArgumentsKind[NumArgs] = Kind; + DiagObj->DiagArgumentsVal[NumArgs++] = V; + } + } + + void AddSourceRange(const SourceRange &R) const { + assert(NumRanges < + sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && + "Too many arguments to diagnostic!"); + if (DiagObj) + DiagObj->DiagRanges[NumRanges++] = R; + } + + void AddFixItHint(const FixItHint &Hint) const { + if (Hint.isNull()) + return; + + assert(NumFixItHints < Diagnostic::MaxFixItHints && + "Too many fix-it hints!"); + if (DiagObj) + DiagObj->FixItHints[NumFixItHints++] = Hint; + } +}; + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + llvm::StringRef S) { + DB.AddString(S); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const char *Str) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), + Diagnostic::ak_c_string); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { + DB.AddTaggedVal(I, Diagnostic::ak_sint); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) { + DB.AddTaggedVal(I, Diagnostic::ak_sint); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + unsigned I) { + DB.AddTaggedVal(I, Diagnostic::ak_uint); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const IdentifierInfo *II) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), + Diagnostic::ak_identifierinfo); + return DB; +} + +// Adds a DeclContext to the diagnostic. The enable_if template magic is here +// so that we only match those arguments that are (statically) DeclContexts; +// other arguments that derive from DeclContext (e.g., RecordDecls) will not +// match. +template<typename T> +inline +typename llvm::enable_if<llvm::is_same<T, DeclContext>, + const DiagnosticBuilder &>::type +operator<<(const DiagnosticBuilder &DB, T *DC) { + DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), + Diagnostic::ak_declcontext); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const SourceRange &R) { + DB.AddSourceRange(R); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const FixItHint &Hint) { + DB.AddFixItHint(Hint); + return DB; +} + +/// Report - Issue the message to the client. DiagID is a member of the +/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder +/// which emits the diagnostics (through ProcessDiag) when it is destroyed. +inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){ + assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); + CurDiagLoc = Loc; + CurDiagID = DiagID; + return DiagnosticBuilder(this); +} +inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) { + return Report(FullSourceLoc(), DiagID); +} + +//===----------------------------------------------------------------------===// +// DiagnosticInfo +//===----------------------------------------------------------------------===// + +/// DiagnosticInfo - This is a little helper class (which is basically a smart +/// pointer that forward info from Diagnostic) that allows clients to enquire +/// about the currently in-flight diagnostic. +class DiagnosticInfo { + const Diagnostic *DiagObj; +public: + explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {} + + const Diagnostic *getDiags() const { return DiagObj; } + unsigned getID() const { return DiagObj->CurDiagID; } + const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; } + + unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } + + /// getArgKind - Return the kind of the specified index. Based on the kind + /// of argument, the accessors below can be used to get the value. + Diagnostic::ArgumentKind getArgKind(unsigned Idx) const { + assert(Idx < getNumArgs() && "Argument index out of range!"); + return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; + } + + /// getArgStdStr - Return the provided argument string specified by Idx. + const std::string &getArgStdStr(unsigned Idx) const { + assert(getArgKind(Idx) == Diagnostic::ak_std_string && + "invalid argument accessor!"); + return DiagObj->DiagArgumentsStr[Idx]; + } + + /// getArgCStr - Return the specified C string argument. + const char *getArgCStr(unsigned Idx) const { + assert(getArgKind(Idx) == Diagnostic::ak_c_string && + "invalid argument accessor!"); + return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); + } + + /// getArgSInt - Return the specified signed integer argument. + int getArgSInt(unsigned Idx) const { + assert(getArgKind(Idx) == Diagnostic::ak_sint && + "invalid argument accessor!"); + return (int)DiagObj->DiagArgumentsVal[Idx]; + } + + /// getArgUInt - Return the specified unsigned integer argument. + unsigned getArgUInt(unsigned Idx) const { + assert(getArgKind(Idx) == Diagnostic::ak_uint && + "invalid argument accessor!"); + return (unsigned)DiagObj->DiagArgumentsVal[Idx]; + } + + /// getArgIdentifier - Return the specified IdentifierInfo argument. + const IdentifierInfo *getArgIdentifier(unsigned Idx) const { + assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo && + "invalid argument accessor!"); + return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); + } + + /// getRawArg - Return the specified non-string argument in an opaque form. + intptr_t getRawArg(unsigned Idx) const { + assert(getArgKind(Idx) != Diagnostic::ak_std_string && + "invalid argument accessor!"); + return DiagObj->DiagArgumentsVal[Idx]; + } + + + /// getNumRanges - Return the number of source ranges associated with this + /// diagnostic. + unsigned getNumRanges() const { + return DiagObj->NumDiagRanges; + } + + SourceRange getRange(unsigned Idx) const { + assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); + return DiagObj->DiagRanges[Idx]; + } + + unsigned getNumFixItHints() const { + return DiagObj->NumFixItHints; + } + + const FixItHint &getFixItHint(unsigned Idx) const { + return DiagObj->FixItHints[Idx]; + } + + const FixItHint *getFixItHints() const { + return DiagObj->NumFixItHints? + &DiagObj->FixItHints[0] : 0; + } + + /// FormatDiagnostic - Format this diagnostic into a string, substituting the + /// formal arguments into the %0 slots. The result is appended onto the Str + /// array. + void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const; + + /// FormatDiagnostic - Format the given format-string into the + /// output buffer using the arguments stored in this diagnostic. + void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, + llvm::SmallVectorImpl<char> &OutStr) const; +}; + +/** + * \brief Represents a diagnostic in a form that can be serialized and + * deserialized. + */ +class StoredDiagnostic { + Diagnostic::Level Level; + FullSourceLoc Loc; + std::string Message; + std::vector<SourceRange> Ranges; + std::vector<FixItHint> FixIts; + +public: + StoredDiagnostic(); + StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); + StoredDiagnostic(Diagnostic::Level Level, llvm::StringRef Message); + ~StoredDiagnostic(); + + /// \brief Evaluates true when this object stores a diagnostic. + operator bool() const { return Message.size() > 0; } + + Diagnostic::Level getLevel() const { return Level; } + const FullSourceLoc &getLocation() const { return Loc; } + llvm::StringRef getMessage() const { return Message; } + + typedef std::vector<SourceRange>::const_iterator range_iterator; + range_iterator range_begin() const { return Ranges.begin(); } + range_iterator range_end() const { return Ranges.end(); } + unsigned range_size() const { return Ranges.size(); } + + typedef std::vector<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(); } + + /// Serialize - Serialize the given diagnostic (with its diagnostic + /// level) to the given stream. Serialization is a lossy operation, + /// since the specific diagnostic ID and any macro-instantiation + /// information is lost. + void Serialize(llvm::raw_ostream &OS) const; + + /// Deserialize - Deserialize the first diagnostic within the memory + /// [Memory, MemoryEnd), producing a new diagnostic builder describing the + /// deserialized diagnostic. If the memory does not contain a + /// diagnostic, returns a diagnostic builder with no diagnostic ID. + static StoredDiagnostic Deserialize(FileManager &FM, SourceManager &SM, + const char *&Memory, const char *MemoryEnd); +}; + +/// DiagnosticClient - This is an abstract interface implemented by clients of +/// the front-end, which formats and prints fully processed diagnostics. +class DiagnosticClient { +public: + virtual ~DiagnosticClient(); + + /// BeginSourceFile - Callback to inform the diagnostic client that processing + /// of a source file is beginning. + /// + /// Note that diagnostics may be emitted outside the processing of a source + /// file, for example during the parsing of command line options. However, + /// diagnostics with source range information are required to only be emitted + /// in between BeginSourceFile() and EndSourceFile(). + /// + /// \arg LO - The language options for the source file being processed. + /// \arg PP - The preprocessor object being used for the source; this optional + /// and may not be present, for example when processing AST source files. + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP = 0) {} + + /// EndSourceFile - Callback to inform the diagnostic client that processing + /// of a source file has ended. The diagnostic client should assume that any + /// objects made available via \see BeginSourceFile() are inaccessible. + virtual void EndSourceFile() {} + + /// IncludeInDiagnosticCounts - This method (whose default implementation + /// returns true) indicates whether the diagnostics handled by this + /// DiagnosticClient should be included in the number of diagnostics reported + /// by Diagnostic. + virtual bool IncludeInDiagnosticCounts() const; + + /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or + /// capturing it to a log as needed. + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info) = 0; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td new file mode 100644 index 0000000..fabf9eb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td @@ -0,0 +1,87 @@ +//===--- Diagnostic.td - C Language Family Diagnostic Handling ------------===// +// +// 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 TableGen core definitions for the diagnostics +// and diagnostic control. +// +//===----------------------------------------------------------------------===// + +// Define the diagnostic mappings. +class DiagMapping; +def MAP_IGNORE : DiagMapping; +def MAP_WARNING : DiagMapping; +def MAP_ERROR : DiagMapping; +def MAP_FATAL : DiagMapping; + +// Define the diagnostic classes. +class DiagClass; +def CLASS_NOTE : DiagClass; +def CLASS_WARNING : DiagClass; +def CLASS_EXTENSION : DiagClass; +def CLASS_ERROR : DiagClass; + +// Diagnostic Categories. These can be applied to groups or individual +// diagnostics to specify a category. +class DiagCategory<string Name> { + string CategoryName = Name; +} + +// Diagnostic Groups. +class DiagGroup<string Name, list<DiagGroup> subgroups = []> { + string GroupName = Name; + list<DiagGroup> SubGroups = subgroups; + string CategoryName = ""; +} +class InGroup<DiagGroup G> { DiagGroup Group = G; } +//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; } + + +// This defines all of the named diagnostic categories. +include "DiagnosticCategories.td" + +// This defines all of the named diagnostic groups. +include "DiagnosticGroups.td" + + +// All diagnostics emitted by the compiler are an indirect subclass of this. +class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> { + /// Component is specified by the file with a big let directive. + string Component = ?; + string Text = text; + DiagClass Class = DC; + bit SFINAE = 1; + DiagMapping DefaultMapping = defaultmapping; + DiagGroup Group; + string CategoryName = ""; +} + +class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>; +class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>; +class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>; +class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>; +class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>; + + +class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; } +class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; } +class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; } +class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; } + +class NoSFINAE { bit SFINAE = 0; } + +// Definitions for Diagnostics. +include "DiagnosticASTKinds.td" +include "DiagnosticAnalysisKinds.td" +include "DiagnosticCommonKinds.td" +include "DiagnosticDriverKinds.td" +include "DiagnosticFrontendKinds.td" +include "DiagnosticLexKinds.td" +include "DiagnosticParseKinds.td" +include "DiagnosticSemaKinds.td" + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td new file mode 100644 index 0000000..d755d99 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -0,0 +1,84 @@ +//==--- DiagnosticASTKinds.td - libast diagnostics ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "AST" in { + +//def note_comma_in_ice : Note< +// "C does not permit evaluated commas in an integer constant expression">; +def note_expr_divide_by_zero : Note<"division by zero">; + +// inline asm related. +let CategoryName = "Inline Assembly Issue" in { + def err_asm_invalid_escape : Error< + "invalid %% escape in inline assembly string">; + def err_asm_unknown_symbolic_operand_name : Error< + "unknown symbolic operand name in inline assembly string">; + + def err_asm_unterminated_symbolic_operand_name : Error< + "unterminated symbolic operand name in inline assembly string">; + def err_asm_empty_symbolic_operand_name : Error< + "empty symbolic operand name in inline assembly string">; + def err_asm_invalid_operand_number : Error< + "invalid operand number in inline asm string">; +} + + +// Importing ASTs +def err_odr_variable_type_inconsistent : Error< + "external variable %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def err_odr_variable_multiple_def : Error< + "external variable %0 defined in multiple translation units">; +def note_odr_value_here : Note<"declared here with type %0">; +def note_odr_defined_here : Note<"also defined here">; +def err_odr_function_type_inconsistent : Error< + "external function %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def warn_odr_tag_type_inconsistent : Warning< + "type %0 has incompatible definitions in different translation units">; +def note_odr_tag_kind_here: Note< + "%0 is a %select{struct|union|class|enum}1 here">; +def note_odr_field : Note<"field %0 has type %1 here">; +def note_odr_missing_field : Note<"no corresponding field here">; +def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">; +def note_odr_not_bit_field : Note<"field %0 is not a bit-field">; +def note_odr_base : Note<"class has base type %0">; +def note_odr_virtual_base : Note< + "%select{non-virtual|virtual}0 derivation here">; +def note_odr_missing_base : Note<"no corresponding base class here">; +def note_odr_number_of_bases : Note< + "class has %0 base %plural{1:class|:classes}0">; +def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; +def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; +def err_odr_ivar_type_inconsistent : Error< + "instance variable %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def err_odr_objc_superclass_inconsistent : Error< + "class %0 has incompatible superclasses">; +def note_odr_objc_superclass : Note<"inherits from superclass %0 here">; +def note_odr_objc_missing_superclass : Note<"no corresponding superclass here">; +def err_odr_objc_method_result_type_inconsistent : Error< + "%select{class|instance}0 method %1 has incompatible result types in " + "different translation units (%2 vs. %3)">; +def err_odr_objc_method_num_params_inconsistent : Error< + "%select{class|instance}0 method %1 has a different number of parameters in " + "different translation units (%2 vs. %3)">; +def err_odr_objc_method_param_type_inconsistent : Error< + "%select{class|instance}0 method %1 has a parameter with a different types " + "in different translation units (%2 vs. %3)">; +def err_odr_objc_method_variadic_inconsistent : Error< + "%select{class|instance}0 method %1 is variadic in one translation unit " + "and not variadic in another">; +def note_odr_objc_method_here : Note< + "%select{class|instance}0 method %1 also declared here">; +def err_odr_objc_property_type_inconsistent : Error< + "property %0 declared with incompatible types in different " + "translation units (%1 vs. %2)">; +def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">; +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td new file mode 100644 index 0000000..46dc0e6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td @@ -0,0 +1,15 @@ +//==--- DiagnosticAnalysisKinds.td - libanalysis diagnostics --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +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/DiagnosticCategories.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td new file mode 100644 index 0000000..a02fbdf --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td @@ -0,0 +1,10 @@ +//==--- DiagnosticCategories.td - Diagnostic Category Definitions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +class CatInlineAsm : DiagCategory<"Inline Assembly Issue">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td new file mode 100644 index 0000000..88e7dc1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -0,0 +1,77 @@ +//==--- DiagnosticCommonKinds.td - common diagnostics ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Common Helpers +//===----------------------------------------------------------------------===// + +let Component = "Common" in { + +// Basic. + +def fatal_too_many_errors + : Error<"too many errors emitted, stopping now">, DefaultFatal; + +def note_previous_definition : Note<"previous definition is here">; +def note_previous_declaration : Note<"previous declaration is here">; +def note_previous_implicit_declaration : Note< + "previous implicit declaration is here">; +def note_previous_use : Note<"previous use is here">; +def note_duplicate_case_prev : Note<"previous case defined here">; +def note_forward_declaration : Note<"forward declaration of %0">; +def note_type_being_defined : Note< + "definition of %0 is not complete until the closing '}'">; +/// note_matching - this is used as a continuation of a previous diagnostic, +/// e.g. to specify the '(' when we expected a ')'. +def note_matching : Note<"to match this '%0'">; + +def note_using : Note<"using">; +def note_also_found : Note<"also found">; + +// Parse && Lex +def err_expected_colon : Error<"expected ':'">; +def err_expected_colon_after_setter_name : Error< + "method name referenced in property setter attribute " + "must end with ':'">; + +// Parse && Sema +def ext_no_declarators : ExtWarn<"declaration does not declare anything">; +def err_param_redefinition : Error<"redefinition of parameter %0">; +def err_invalid_storage_class_in_func_decl : Error< + "invalid storage class specifier in function declarator">; +def err_expected_namespace_name : Error<"expected namespace name">; + +// Sema && Lex +def ext_longlong : Extension< + "'long long' is an extension when C99 mode is not enabled">, + InGroup<LongLong>; +def warn_integer_too_large : Warning< + "integer constant is too large for its type">; +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">; + +// Targets + +def err_target_unknown_triple : Error< + "unknown target triple '%0', please use -triple or -arch">; +def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; +def err_target_unknown_abi : Error<"unknown target ABI '%0'">; +def err_target_invalid_feature : Error<"invalid target feature '%0'">; + +// Source manager +def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; +def err_file_modified : Error< + "file '%0' modified since it was first processed">, DefaultFatal; +def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " + "encoding is not supported">, DefaultFatal; +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td new file mode 100644 index 0000000..f4a31cc --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -0,0 +1,102 @@ +//==--- DiagnosticDriverKinds.td - libdriver diagnostics ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "Driver" in { + +def err_drv_no_such_file : Error<"no such file or directory: '%0'">; +def err_drv_unsupported_opt : Error<"unsupported option '%0'">; +def err_drv_unknown_stdin_type : Error< + "-E or -x required when input is from standard input">; +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_opt_with_multiple_archs : Error< + "option '%0' cannot be used with multiple -arch options">; +def err_drv_invalid_output_with_multiple_archs : Error< + "cannot use '%0' output with multiple -arch options">; +def err_drv_no_input_files : Error<"no input files">; +def err_drv_use_of_Z_option : Error< + "unsupported use of internal gcc -Z option '%0'">; +def err_drv_output_argument_with_multiple_files : Error< + "cannot specify -o when generating multiple output files">; +def err_drv_unable_to_make_temp : Error< + "unable to make temporary file: %0">; +def err_drv_unable_to_remove_file : Error< + "unable to remove file: %0">; +def err_drv_command_failure : Error< + "unable to execute command: %0">; +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)">; +def err_drv_invalid_Xarch_argument : Error< + "invalid Xarch argument: '%0'">; +def err_drv_argument_only_allowed_with : Error< + "invalid argument '%0' only allowed with '%1'">; +def err_drv_argument_not_allowed_with : Error< + "invalid argument '%0' not allowed with '%1'">; +def err_drv_invalid_version_number : Error< + "invalid version number in '%0'">; +def err_drv_no_linker_llvm_support : Error< + "'%0': unable to pass LLVM bit-code files to linker">; +def err_drv_no_ast_support : Error< + "'%0': unable to use AST files with this tool">; +def err_drv_clang_unsupported : Error< + "the clang compiler does not support '%0'">; +def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error< + "the clang compiler does not support '%0' for C++ on Darwin/i386">; +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)">; +def err_drv_invalid_mfloat_abi : Error< + "invalid float ABI '%0'">; +def err_drv_I_dash_not_supported : Error< + "'%0' not supported, please use -iquote instead">; +def err_drv_unknown_argument : Error<"unknown argument: '%0'">; +def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; +def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; +def err_drv_invalid_remap_file : Error< + "invalid option '%0' not of the form <from-file>;<to-file>">; +def err_drv_invalid_gcc_output_type : Error< + "invalid output type '%0' for use with gcc tool">; +def err_drv_cc_print_options_failure : Error< + "unable to open CC_PRINT_OPTIONS file: %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">; +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< + "not using the clang compiler for C++ inputs">; +def warn_drv_not_using_clang_arch : Warning< + "not using the clang compiler for the '%0' architecture">; +def warn_drv_clang_unsupported : Warning< + "the clang compiler does not support '%0'">; +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_missing_resource_library : Warning< + "missing resource library '%0', link may fail">; +def warn_drv_conflicting_deployment_targets : Warning< + "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">; +def warn_drv_treating_input_as_cxx : Warning< + "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">, + InGroup<Deprecated>; +def warn_drv_objc_gc_unsupported : Warning< + "Objective-C garbage collection is not supported on this platform, ignoring '%0'">; + +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td new file mode 100644 index 0000000..c7cad73 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -0,0 +1,253 @@ +//==--- DiagnosticFrontendKinds.td - frontend diagnostics -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "Frontend" in { + +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<"generated from here">; +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< + "unable to handle compilation, expected exactly one compiler job in '%0'">; +def err_fe_expected_clang_command : Error< + "expected a clang compiler command">; +def err_fe_remap_missing_to_file : Error< + "could not remap file '%0' to the contents of file '%1'">, DefaultFatal; +def err_fe_remap_missing_from_file : Error< + "could not remap from missing file '%0'">, DefaultFatal; +def err_fe_unable_to_load_pch : Error< + "unable to load PCH file">; +def err_fe_unable_to_load_plugin : Error< + "unable to load plugin '%0': '%1'">; +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_open_logfile : Error< + "unable to open logfile file '%0': '%1'">; +def err_fe_pth_file_has_no_source_header : Error< + "PTH file '%0' does not designate an original source header file for -include-pth">; +def warn_fe_macro_contains_embedded_newline : Warning< + "macro '%0' contains embedded newline, text after the newline is ignored.">; + +def err_verify_missing_start : Error< + "cannot find start ('{{') of expected %0">; +def err_verify_missing_end : Error< + "cannot find end ('}}') of expected %0">; +def err_verify_invalid_content : Error< + "invalid expected %0: %1">; +def err_verify_inconsistent_diags : Error< + "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">; + +def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; +def note_fixit_in_macro : Note< + "FIX-IT unable to apply suggested code changes in a macro">; +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_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 warn_pch_c99 : Error< + "C99 support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_cplusplus : Error< + "C++ support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_cplusplus0x : Error< + "C++0x support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_objective_c : Error< + "Objective-C support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; +def warn_pch_objective_c2 : Error< + "Objective-C 2.0 support was %select{disabled|enabled}0 in PCH file but " + "is currently %select{disabled|enabled}1">; +def warn_pch_nonfragile_abi : Error< + "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C " + "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">; +def warn_pch_nonfragile_abi2 : Error< + "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 " + "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 " + "Objective-C ABI is selected">; +def warn_pch_no_constant_cfstrings : Error< + "Objctive-C NSstring generation support was %select{disabled|enabled}0 " + "in PCH file but currently %select{disabled|enabled}1">; +def warn_pch_extensions : Error< + "extensions were %select{enabled|disabled}0 in PCH file but are " + "currently %select{enabled|disabled}1">; +def warn_pch_gnu_extensions : Error< + "GNU extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_gnu_keywords : Error< + "GNU keywords were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_microsoft_extensions : Error< + "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_heinous_extensions : Error< + "heinous extensions were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; +def warn_pch_lax_vector_conversions : Error< + "lax vector conversions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_altivec : Error< + "AltiVec initializers were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_opencl : Error< + "OpenCL language extensions were %select{disabled|enabled}0 in PCH file " + "but are currently %select{disabled|enabled}1">; +def warn_pch_elide_constructors : Error< + "Elidable copy constructors were %select{disabled|enabled}0 in PCH file " + "but are currently %select{disabled|enabled}1">; +def warn_pch_exceptions : Error< + "exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_sjlj_exceptions : Error< + "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_objc_runtime : Error< + "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the " + "%select{NeXT|GNU}1 runtime is selected">; +def warn_pch_freestanding : Error< + "PCH file was compiled with a %select{hosted|freestanding}0 " + "implementation but a %select{hosted|freestanding}1 implementation " + "is selected">; +def warn_pch_builtins : Error< + "PCH file was compiled with builtins %select{enabled|disabled}0 but " + "builtins are currently %select{enabled|disabled}1">; +def warn_pch_thread_safe_statics : Error< + "PCH file was compiled %select{without|with}0 thread-safe statics but " + "thread-safe statics are currently %select{disabled|enabled}1">; +def warn_pch_posix_threads : Error< + "PCH file was compiled %select{without|with}0 POSIX thread support but " + "POSIX threads are currently %select{disabled|enabled}1">; +def warn_pch_stack_protector : Error< + "stack protector was %select{off|on|required}0 in PCH file but " + "is currently %select{off|on|required}1">; +def warn_pch_blocks : Error< + "blocks were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_math_errno : Error< + "math functions %select{do not respect|respect}0 'errno' in PCH " + "file but they are currently set to %select{not respect|respect}1 " + "'errno'">; +def warn_pch_overflow_checking : Error< + "signed integer overflow checking was %select{disabled|enabled}0 in PCH " + "file but is currently %select{disabled|enabled}1">; +def warn_pch_optimize : Error< + "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_optimize_size : Error< + "the macro '__OPTIMIZE_SIZE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_static : Error< + "the PCH file was compiled %select{dynamic|static}0 but the " + "current translation unit is being compiled as %select{dynamic|static}1">; +def warn_pch_pic_level : Error< + "PCH file was compiled with PIC level %0, but the current translation " + "unit will be compiled with PIC level %1">; +def warn_pch_gnu_inline : Error< + "PCH file was compiled with %select{C99|GNU|}0 inline semantics but " + "%select{C99|GNU}1 inline semantics are currently selected">; +def warn_pch_no_inline : Error< + "the macro '__NO_INLINE__' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_gc_mode : Error< + "the PCH file was built with %select{no||hybrid}0 garbage collection but " + "the current translation unit will compiled with %select{no||hybrid}1 " + "garbage collection">; +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 warn_pch_access_control : Error< + "C++ access control was %select{disabled|enabled}0 in the PCH file but " + "is currently %select{disabled|enabled}1">; +def warn_pch_char_signed : Error< + "char was %select{unsigned|signed}0 in the PCH file but " + "is currently %select{unsigned|signed}1">; +def warn_pch_short_wchar : Error< + "-fshort-wchar was %select{disabled|enabled}0 in the PCH file but " + "is currently %select{disabled|enabled}1">; + +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_warning_specifier : Warning< + "unknown %0 warning specifier: '%1'">, + InGroup<DiagGroup<"unknown-warning-option"> >; +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td new file mode 100644 index 0000000..b79bf8e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -0,0 +1,198 @@ +//==--- DiagnosticGroups.td - Diagnostic Group Definitions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +def ImplicitFunctionDeclare : DiagGroup<"implicit-function-declaration">; +def ImplicitInt : DiagGroup<"implicit-int">; + +// Aggregation warning settings. +def Implicit : DiagGroup<"implicit", [ + ImplicitFunctionDeclare, + ImplicitInt +]>; + +// Empty DiagGroups are recognized by clang but ignored. +def : DiagGroup<"address">; +def AddressOfTemporary : DiagGroup<"address-of-temporary">; +def : DiagGroup<"aggregate-return">; +def : DiagGroup<"attributes">; +def : DiagGroup<"bad-function-cast">; +def : DiagGroup<"c++-compat">; +def : DiagGroup<"cast-align">; +def : DiagGroup<"cast-qual">; +def : DiagGroup<"char-align">; +def Comment : DiagGroup<"comment">; +def : DiagGroup<"ctor-dtor-privacy">; +def : DiagGroup<"declaration-after-statement">; +def GNUDesignator : DiagGroup<"gnu-designator">; +def Deprecated : DiagGroup<"deprecated">; +def : DiagGroup<"disabled-optimization">; +def : DiagGroup<"discard-qual">; +def : DiagGroup<"div-by-zero">; +def EmptyBody : DiagGroup<"empty-body">; +def ExtraTokens : DiagGroup<"extra-tokens">; + +def FormatExtraArgs : DiagGroup<"format-extra-args">; +def FormatZeroLength : DiagGroup<"format-zero-length">; + +def CXXHexFloats : DiagGroup<"c++-hex-floats">; + +def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; +def FourByteMultiChar : DiagGroup<"four-char-constants">; +def : DiagGroup<"idiomatic-parentheses">; +def : DiagGroup<"import">; +def : DiagGroup<"init-self">; +def : DiagGroup<"inline">; +def : DiagGroup<"int-to-pointer-cast">; +def : DiagGroup<"invalid-pch">; +def LiteralRange : DiagGroup<"literal-range">; +def MissingBraces : DiagGroup<"missing-braces">; +def : DiagGroup<"missing-declarations">; +def : DiagGroup<"missing-format-attribute">; +def : DiagGroup<"missing-include-dirs">; +def : DiagGroup<"missing-noreturn">; +def MultiChar : DiagGroup<"multichar">; +def : DiagGroup<"nested-externs">; +def : DiagGroup<"newline-eof">; +def LongLong : DiagGroup<"long-long">; +def MismatchedTags : DiagGroup<"mismatched-tags">; +def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; +def NonNull : DiagGroup<"nonnull">; +def : DiagGroup<"nonportable-cfstrings">; +def : DiagGroup<"non-virtual-dtor">; +def : DiagGroup<"old-style-definition">; +def : DiagGroup<"overflow">; +def : DiagGroup<"overloaded-virtual">; +def : DiagGroup<"packed">; +def PointerArith : DiagGroup<"pointer-arith">; +def : DiagGroup<"pointer-to-int-cast">; +def : DiagGroup<"redundant-decls">; +def ReturnType : DiagGroup<"return-type">; +def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; +def : DiagGroup<"sequence-point">; +def Shadow : DiagGroup<"shadow">; +def : DiagGroup<"shorten-64-to-32">; +def SignCompare : DiagGroup<"sign-compare">; +def : DiagGroup<"synth">; + +// Preprocessor warnings. +def : DiagGroup<"builtin-macro-redefined">; + +// Just silence warnings about -Wstrict-aliasing for now. +def : DiagGroup<"strict-aliasing=0">; +def : DiagGroup<"strict-aliasing=1">; +def : DiagGroup<"strict-aliasing=2">; +def : DiagGroup<"strict-aliasing">; + +// Just silence warnings about -Wstrict-overflow for now. +def : DiagGroup<"strict-overflow=0">; +def : DiagGroup<"strict-overflow=1">; +def : DiagGroup<"strict-overflow=2">; +def : DiagGroup<"strict-overflow=3">; +def : DiagGroup<"strict-overflow=4">; +def : DiagGroup<"strict-overflow=5">; +def : DiagGroup<"strict-overflow">; + +def InvalidOffsetof : DiagGroup<"invalid-offsetof">; +def : DiagGroup<"strict-prototypes">; +def : DiagGroup<"strict-selector-match">; +def SwitchEnum : DiagGroup<"switch-enum">; +def Switch : DiagGroup<"switch", [SwitchEnum]>; +def Trigraphs : DiagGroup<"trigraphs">; + +def : DiagGroup<"type-limits">; +def Uninitialized : DiagGroup<"uninitialized">; +def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def UnusedArgument : DiagGroup<"unused-argument">; +def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; +def UnusedFunction : DiagGroup<"unused-function">; +def UnusedLabel : DiagGroup<"unused-label">; +def UnusedParameter : DiagGroup<"unused-parameter">; +def UnusedValue : DiagGroup<"unused-value">; +def UnusedVariable : DiagGroup<"unused-variable">; +def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; +def Reorder : DiagGroup<"reorder">; +def UndeclaredSelector : DiagGroup<"undeclared-selector">; +def Protocol : DiagGroup<"protocol">; +def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; +def : DiagGroup<"variadic-macros">; +def VariadicMacros : DiagGroup<"variadic-macros">; +def VectorConversions : DiagGroup<"vector-conversions">; // clang specific +def VLA : DiagGroup<"vla">; +def VolatileRegisterVar : DiagGroup<"volatile-register-var">; +def : DiagGroup<"write-strings">; +def CharSubscript : DiagGroup<"char-subscripts">; + +// Aggregation warning settings. + +// -Widiomatic-parentheses contains warnings about 'idiomatic' +// missing parentheses; it is off by default. +def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>; + +// -Wconversion has its own warnings, but we split this one out for +// legacy reasons. +def Conversion : DiagGroup<"conversion", + [DiagGroup<"shorten-64-to-32">]>, + DiagCategory<"Value Conversion Issue">; + +def Unused : DiagGroup<"unused", + [UnusedArgument, UnusedFunction, UnusedLabel, + // UnusedParameter, (matches GCC's behavior) + UnusedValue, UnusedVariable]>, + DiagCategory<"Unused Entity Issue">; + +// Format settings. +def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>, + DiagCategory<"Format String Issue">; +def FormatSecurity : DiagGroup<"format-security", [Format]>; +def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>; +def FormatY2K : DiagGroup<"format-y2k", [Format]>; +def Format2 : DiagGroup<"format=2", + [FormatNonLiteral, FormatSecurity, FormatY2K]>; + +def Extra : DiagGroup<"extra", [ + MissingFieldInitializers, + SemiBeforeMethodBody, + SignCompare, + UnusedParameter + ]>; + +def Most : DiagGroup<"most", [ + CharSubscript, + Comment, + Format, + Implicit, + MismatchedTags, + MissingBraces, + MultiChar, + Reorder, + ReturnType, + Switch, + Trigraphs, + Uninitialized, + UnknownPragmas, + Unused, + VectorConversions, + VolatileRegisterVar + ]>; + +// -Wall is -Wmost -Wparentheses +def : DiagGroup<"all", [Most, Parentheses]>; + +// Aliases. +def : DiagGroup<"", [Extra]>; // -W = -Wextra +def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens +def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment + +// A warning group for warnings that we want to have on by default in clang, +// but which aren't on by default in GCC. +def NonGCC : DiagGroup<"non-gcc", + [SignCompare, Conversion, LiteralRange]>; + +// A warning group for warnings about GCC extensions. +def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td new file mode 100644 index 0000000..848e85c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -0,0 +1,300 @@ +//==--- DiagnosticLexKinds.td - liblex diagnostics ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Lexer Diagnostics +//===----------------------------------------------------------------------===// + +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 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">; + +// Trigraphs. +def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>; +def trigraph_ignored_block_comment : Warning< + "ignored trigraph would end block comment">, InGroup<Trigraphs>; +def trigraph_ends_block_comment : Warning<"trigraph ends block comment">, + InGroup<Trigraphs>; +def trigraph_converted : Warning<"trigraph converted to '%0' character">, + InGroup<Trigraphs>; + +def ext_multi_line_bcpl_comment : Extension<"multi-line // comment">, + InGroup<Comment>; +def ext_bcpl_comment : Extension< + "// comments are not allowed in this language">, + InGroup<Comment>; +def ext_no_newline_eof : Extension<"no newline at end of file">; +def ext_backslash_newline_eof : Extension<"backslash-newline at end of file">; +def ext_dollar_in_identifier : Extension<"'$' in identifier">; +def charize_microsoft_ext : Extension<"@# is a microsoft extension">; + +def ext_token_used : Extension<"extension used">; + +def err_unterminated_string : Error<"missing terminating '\"' character">; +def err_unterminated_char : Error<"missing terminating ' character">; +def err_empty_character : Error<"empty character constant">; +def err_unterminated_block_comment : Error<"unterminated /* comment">; +def err_invalid_character_to_charify : Error< + "invalid argument to convert to character">; + +def err_conflict_marker : Error<"version control conflict marker in file">; + +def ext_multichar_character_literal : ExtWarn< + "multi-character character constant">, InGroup<MultiChar>; +def ext_four_char_character_literal : Extension< + "multi-character character constant">, InGroup<FourByteMultiChar>; + + +// Literal +def ext_nonstandard_escape : Extension< + "use of non-standard escape character '\\%0'">; +def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">; +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_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">; +def err_invalid_suffix_integer_constant : Error< + "invalid suffix '%0' on integer constant">; +def err_invalid_suffix_float_constant : Error< + "invalid suffix '%0' on floating constant">; +def warn_extraneous_wide_char_constant : Warning< + "extraneous characters in wide character constant ignored">; +def warn_char_constant_too_large : Warning< + "character constant too long for its type">; +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 ext_hexconstant_cplusplus : Extension< + "hexadecimal floating constants are a C99 feature that is incompatible with " + "C++0x">, InGroup<CXXHexFloats>; +def ext_hexconstant_invalid : Extension< + "hexadecimal floating constants are a C99 feature">; +def ext_binary_literal : Extension< + "binary integer literals are an extension">; +def err_pascal_string_too_long : Error<"Pascal string is too long">; +def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">; +def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; + +//===----------------------------------------------------------------------===// +// 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">, InGroup<DiagGroup<"#warnings">>; +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">; +def ext_missing_whitespace_after_macro_name : ExtWarn< + "whitespace required after macro name">; +def warn_missing_whitespace_after_macro_name : Warning< + "whitespace recommended after macro name">; + +def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">; +def pp_pragma_sysheader_in_main_file : Warning< + "#pragma system_header ignored in main file">; +def pp_poisoning_existing_macro : Warning<"poisoning existing macro">; +def pp_out_of_date_dependency : Warning< + "current file is older than dependency %0">; +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_macro_not_used : Warning<"macro is not used">, DefaultIgnore, + InGroup<DiagGroup<"unused-macros">>; +def warn_pp_undef_identifier : Warning< + "%0 is not defined, evaluates to 0">, + InGroup<DiagGroup<"undef">>, DefaultIgnore; + +def pp_invalid_string_literal : Warning< + "invalid string literal, ignoring final '\\'">; +def warn_pp_expr_overflow : Warning< + "integer overflow in preprocessor expression">; +def warn_pp_convert_lhs_to_positive : Warning< + "left side of operator converted from negative value to unsigned: %0">; +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_ident_directive : Extension<"#ident is a language extension">; +def ext_pp_include_next_directive : Extension< + "#include_next is a language extension">; +def ext_pp_warning_directive : Extension<"#warning is a language extension">; + +def ext_pp_extra_tokens_at_eol : ExtWarn< + "extra tokens at end of #%0 directive">, InGroup<ExtraTokens>; + +def ext_pp_comma_expr : Extension<"comma operator in operand of #if">; +def ext_pp_bad_vaargs_use : Extension< + "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">; +def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">; +def ext_variadic_macro : Extension<"variadic macros were introduced in C99">, + InGroup<VariadicMacros>; +def ext_named_variadic_macro : Extension< + "named variadic macros are a GNU extension">, InGroup<VariadicMacros>; +def ext_embedded_directive : Extension< + "embedding a directive within macro arguments is not portable">; +def ext_missing_varargs_arg : Extension< + "varargs argument missing, but tolerated as an extension">; +def ext_empty_fnmacro_arg : Extension< + "empty macro arguments were standardized in C99">; + +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; +def err_pp_empty_filename : Error<"empty filename">; +def err_pp_include_too_deep : Error<"#include nested too deeply">; +def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">; +def err_pp_macro_not_identifier : Error<"macro names must be identifiers">; +def err_pp_missing_macro_name : Error<"macro name missing">; +def err_pp_missing_rparen_in_macro_def : Error< + "missing ')' in macro parameter list">; +def err_pp_invalid_tok_in_arg_list : Error< + "invalid token in macro parameter list">; +def err_pp_expected_ident_in_arg_list : Error< + "expected identifier in macro parameter list">; +def err_pp_expected_comma_in_arg_list : Error< + "expected comma in macro parameter list">; +def err_pp_duplicate_name_in_arg_list : Error< + "duplicate macro parameter name %0">; +def err_pp_stringize_not_parameter : Error< + "'#' is not followed by a macro parameter">; +def err_pp_malformed_ident : Error<"invalid #ident directive">; +def err_pp_unterminated_conditional : Error< + "unterminated conditional directive">; +def pp_err_else_after_else : Error<"#else after #else">; +def pp_err_elif_after_else : Error<"#elif after #else">; +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">; +def err_pp_defined_requires_identifier : Error< + "operator 'defined' requires an identifier">; +def err_pp_missing_lparen : Error<"missing '(' after '%0'">; +def err_pp_missing_rparen : Error<"missing ')' after '%0'">; +def err_pp_colon_without_question : Error<"':' without preceding '?'">; +def err_pp_division_by_zero : Error< + "division by zero in preprocessor expression">; +def err_pp_remainder_by_zero : Error< + "remainder by zero in preprocessor expression">; +def err_pp_expr_bad_token_binop : Error< + "token is not a valid binary operator in a preprocessor subexpression">; +def err_pp_expr_bad_token_start_expr : Error< + "invalid token at start of a preprocessor expression">; +def err_pp_invalid_poison : Error<"can only poison identifier tokens">; +def err_pp_used_poisoned_id : Error<"attempt to use a poisoned identifier">; + +def err_feature_check_malformed : Error< + "builtin feature check macro requires a parenthesized identifier">; + +def err__Pragma_malformed : Error< + "_Pragma takes a parenthesized string literal">; +def err_pragma_comment_malformed : Error< + "pragma comment requires parenthesized identifier and optional string">; +def warn_pragma_ignored : Warning<"unknown pragma ignored">, + InGroup<UnknownPragmas>, DefaultIgnore; +def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, + InGroup<UnknownPragmas>; +def ext_stdc_pragma_syntax : + ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">, + InGroup<UnknownPragmas>; +def ext_stdc_pragma_syntax_eom : + ExtWarn<"expected end of macro in STDC pragma">, + InGroup<UnknownPragmas>; +def warn_stdc_fenv_access_not_supported : + Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_gcc_invalid : + ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or" + " 'fatal'">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_clang_invalid : + ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'" + " 'push', or 'pop'">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_clang_cannot_ppp : + ExtWarn<"pragma diagnostic pop could not pop, no matching push">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_invalid_option : + ExtWarn<"pragma diagnostic expected option name (e.g. \"-Wundef\")">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_invalid_token : + ExtWarn<"unexpected token in pragma diagnostic">, + InGroup<UnknownPragmas>; +def warn_pragma_diagnostic_unknown_warning : + ExtWarn<"unknown warning group '%0', ignored">, + InGroup<UnknownPragmas>; + +def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; +def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; +def err_paste_at_start : Error< + "'##' cannot appear at start of macro expansion">; +def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">; +def ext_paste_comma : Extension< + "Use of comma pasting extension is non-portable">; +def err_unterm_macro_invoc : Error< + "unterminated function-like macro invocation">; +def err_too_many_args_in_macro_invoc : Error< + "too many arguments provided to function-like macro invocation">; +def err_too_few_args_in_macro_invoc : Error< + "too few arguments provided to function-like macro invocation">; +def err_pp_bad_paste : Error< + "pasting formed '%0', an invalid preprocessing token">; +def err_pp_operator_used_as_macro_name : Error< + "C++ operator '%0' cannot be used as a macro name">; +def err_pp_illegal_floating_literal : Error< + "floating point literal in preprocessor expression">; +def err_pp_line_requires_integer : Error< + "#line directive requires a positive integer argument">; +def err_pp_line_invalid_filename : Error< + "invalid filename for #line directive">; +def warn_pp_line_decimal : Warning< + "#line directive interprets number as decimal, not octal">; +def err_pp_line_digit_sequence : Error< + "#line directive requires a simple digit sequence">; +def err_pp_linemarker_requires_integer : Error< + "line marker directive requires a positive integer argument">; +def err_pp_linemarker_invalid_filename : Error< + "invalid filename for line marker directive">; +def err_pp_linemarker_invalid_flag : Error< + "invalid flag line marker directive">; +def err_pp_linemarker_invalid_pop : Error< + "invalid line marker flag '2': cannot pop empty include stack">; +def ext_pp_line_too_big : Extension< + "C requires #line number to be less than %0, allowed as extension">; + +} diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td new file mode 100644 index 0000000..934bd0d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -0,0 +1,387 @@ +//==--- DiagnosticParseKinds.td - libparse diagnostics --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Parser Diagnostics +//===----------------------------------------------------------------------===// + +let Component = "Parse" in { + +def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">, + CatInlineAsm; +def warn_file_asm_volatile : Warning< + "meaningless 'volatile' on asm outside function">, CatInlineAsm; + +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 ext_extra_struct_semi : Extension< + "extra ';' inside a struct or union">; + +def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; +def ext_plain_complex : ExtWarn< + "plain '_Complex' requires a type specifier; assuming '_Complex double'">; +def ext_integer_complex : Extension< + "complex integer types are an extension">; +def ext_thread_before : Extension<"'__thread' before 'static'">; + +def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">; + +def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; +def err_invalid_short_spec : Error<"'short %0' is invalid">; +def err_invalid_long_spec : Error<"'long %0' is invalid">; +def err_invalid_longlong_spec : Error<"'long long %0' is invalid">; +def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">; +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">; +def ext_c99_compound_literal : Extension< + "compound literals are a C99-specific feature">; +def ext_enumerator_list_comma : Extension< + "commas at the end of enumerator lists are a %select{C99|C++0x}0-specific " + "feature">; + +def ext_gnu_indirect_goto : Extension< + "use of GNU indirect-goto extension">, InGroup<GNU>; +def ext_gnu_address_of_label : Extension< + "use of GNU address-of-label extension">, InGroup<GNU>; +def ext_gnu_statement_expr : Extension< + "use of GNU statement expression extension">, InGroup<GNU>; +def ext_gnu_conditional_expr : Extension< + "use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>; +def ext_gnu_empty_initializer : Extension< + "use of GNU empty initializer extension">, InGroup<GNU>; +def ext_gnu_array_range : Extension<"use of GNU array range extension">, + InGroup<GNUDesignator>; +def ext_gnu_missing_equal_designator : ExtWarn< + "use of GNU 'missing =' extension in designator">, + InGroup<GNUDesignator>; +def err_expected_equal_designator : Error<"expected '=' or another designator">; +def ext_gnu_old_style_field_designator : ExtWarn< + "use of GNU old-style field designator extension">, + InGroup<GNUDesignator>; +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_expected_ident : Error<"expected identifier">; +def err_expected_ident_lparen : Error<"expected identifier or '('">; +def err_expected_ident_lbrace : Error<"expected identifier or '{'">; +def err_expected_lbrace : Error<"expected '{'">; +def err_expected_lparen : Error<"expected '('">; +def err_expected_rparen : Error<"expected ')'">; +def err_expected_lsquare : Error<"expected '['">; +def err_expected_rsquare : Error<"expected ']'">; +def err_expected_rbrace : Error<"expected '}'">; +def err_expected_greater : Error<"expected '>'">; +def err_expected_semi_declaration : Error< + "expected ';' at end of declaration">; +def err_expected_semi_decl_list : Error< + "expected ';' at end of declaration list">; +def ext_expected_semi_decl_list : Extension< + "expected ';' at end of declaration list">; +def err_expected_member_name_or_semi : Error< + "expected member name or ';' after declaration specifiers">; +def err_function_declared_typedef : Error< + "function definition declared 'typedef'">; +def err_expected_fn_body : Error< + "expected function body after function declarator">; +def err_expected_method_body : Error<"expected method body">; +def err_invalid_token_after_toplevel_declarator : Error< + "invalid token after top level declarator">; +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">; +def err_expected_less_after : Error<"expected '<' after '%0'">; +def err_expected_comma : Error<"expected ','">; +def err_expected_lbrace_in_compound_literal : Error< + "expected '{' in compound literal">; +def err_expected_while : Error<"expected 'while' in do/while loop">; + +def err_expected_semi_after : Error<"expected ';' after %0">; +def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">; +def err_expected_semi_after_expr : Error<"expected ';' after expression">; +def err_expected_semi_after_method_proto : Error< + "expected ';' after method prototype">; +def err_expected_semi_after_namespace_name : Error< + "expected ';' after namespace name">; +def err_unexpected_namespace_attributes_alias : Error< + "attributes can not be specified on namespace alias">; +def err_namespace_nonnamespace_scope : Error< + "namespaces can only be defined in global or namespace scope">; +def err_expected_semi_after_attribute_list : Error< + "expected ';' after attribute list">; +def err_expected_semi_after_static_assert : Error< + "expected ';' after static_assert">; +def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">; +def err_expected_colon_after : Error<"expected ':' after %0">; +def err_label_end_of_compound_statement : Error< + "label at end of compound statement: expected statement">; +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_expected_selector_for_method : Error< + "expected selector for Objective-C method">; +def err_expected_property_name : Error<"expected property name">; + +def err_unexpected_at : Error<"unexpected '@' in program">; + +def err_invalid_reference_qualifier_application : Error< + "'%0' qualifier may not be applied to a reference">; +def err_illegal_decl_reference_to_reference : Error< + "%0 declared as a reference to a reference">; +def err_rvalue_reference : Error< + "rvalue references are only allowed in C++0x">; +def err_argument_required_after_attribute : Error< + "argument required after attribute">; +def err_missing_param : Error<"expected parameter declarator">; +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 err_expected_class_name : Error<"expected class name">; +def err_unspecified_vla_size_with_static : Error< + "'static' may not be used with an unspecified variable length array size">; + +// Declarations. +def err_typename_requires_specqual : Error< + "type name requires a specifier or qualifier">; +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_invalid_decl_spec_combination : Error< + "cannot combine with previous '%0' declaration specifier">; +def err_invalid_vector_decl_spec_combination : Error< + "cannot combine with previous '%0' declaration specifier. '__vector' must be first">; +def err_invalid_pixel_decl_spec_combination : Error< + "'__pixel' must be preceded by '__vector'. '%0' declaration specifier not allowed here">; +def err_invalid_vector_double_decl_spec_combination : Error< + "cannot use 'double' with '__vector'">; +def warn_vector_long_decl_spec_combination : Warning< + "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; +def err_friend_invalid_in_context : Error< + "'friend' used outside of class">; +def err_unknown_typename : Error< + "unknown type name %0">; +def err_use_of_tag_name_without_tag : Error< + "must use '%1' tag to refer to type %0%select{| in this scope}2">; +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">; + +/// 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 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_objc_illegal_visibility_spec : Error< + "illegal visibility specification">; +def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">; +def err_objc_expected_equal : Error< + "setter/getter expects '=' followed by name">; +def err_objc_property_requires_field_name : Error< + "property requires fields to be named">; +def err_objc_property_bitfield : Error<"property name cannot be a bitfield">; +def err_objc_expected_property_attr : Error<"unknown property attribute %0">; +def err_objc_propertoes_require_objc2 : Error< + "properties are an Objective-C 2 feature">; +def err_objc_unexpected_attr : Error< + "prefix attribute must be followed by an interface or protocol">; +def err_objc_directive_only_in_protocol : Error< + "directive may only be specified in protocols only">; +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 warn_expected_implementation : Warning< + "@end must appear in an @implementation context">; +def error_property_ivar_decl : Error< + "property synthesize requires specification of an ivar">; +def err_synthesized_property_name : Error< + "expected a property name in @synthesize">; +def warn_semicolon_before_method_body : Warning< + "semicolon before method body is ignored">, + InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore; + +def err_expected_field_designator : Error< + "expected a field designator, such as '.field = 4'">; + +def err_declaration_does_not_declare_param : Error< + "declaration does not declare a parameter">; +def err_no_matching_param : Error<"parameter named %0 is missing">; + +/// C++ parser diagnostics +def err_expected_unqualified_id : Error< + "expected %select{identifier|unqualified-id}0">; +def err_func_def_no_params : Error< + "function definition does not declare parameters">; +def err_expected_lparen_after_type : Error< + "expected '(' for function-style cast or type construction">; +def err_expected_equal_after_declarator : Error< + "expected '=' after declarator">; +def warn_parens_disambiguated_as_function_decl : Warning< + "parentheses were disambiguated as a function declarator">; +def err_expected_member_or_base_name : Error< + "expected class member or base class name">; +def err_expected_lbrace_after_base_specifiers : Error< + "expected '{' after base class list">; +def ext_ellipsis_exception_spec : Extension< + "exception specification of '...' is a Microsoft extension">; +def err_expected_catch : Error<"expected catch">; +def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; +def err_using_namespace_in_class : Error< + "'using namespace' is not allowed in classes">; +def err_destructor_tilde_identifier : Error< + "expected a class name after '~' to name a destructor">; +def err_destructor_template_id : Error< + "destructor name %0 does not refer to a template">; + +// C++ derived classes +def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; + +// C++ operator overloading +def err_operator_missing_type_specifier : Error< + "missing type specifier after 'operator'">; +def err_operator_string_not_empty : Error< + "string literal after 'operator' must be '\"\"'">; + +// Classes. +def err_anon_type_definition : Error< + "declaration of anonymous %0 must be a definition">; + +def err_cxx0x_attribute_forbids_arguments : Error< + "C++0x attribute '%0' cannot have an argument list">; +def err_cxx0x_attribute_requires_arguments : Error< + "C++0x attribute '%0' must have an argument list">; +def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; + +/// C++ Templates +def err_expected_template : Error<"expected template">; +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_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++0x">; +def err_multiple_template_declarators : Error< + "%select{|a template declaration|an explicit template specialization|" + "an explicit template instantiation}0 can " + "only %select{|declare|declare|instantiate}0 a single entity">; +def err_explicit_instantiation_with_definition : Error< + "explicit template instantiation cannot have a definition; if this " + "definition is meant to be an explicit specialization, add '<>' after the " + "'template' keyword">; +def err_enum_template : Error<"enumeration cannot be a template">; + +def err_missing_dependent_template_keyword : Error< + "use 'template' keyword to treat '%0' as a dependent template name">; + +// Constructor template diagnostics. +def err_out_of_line_constructor_template_id : Error< + "out-of-line constructor for %0 cannot have template arguments">; +def err_out_of_line_template_id_names_constructor : Error< + "qualified reference to %0 is a constructor name rather than a " + "template name wherever a constructor can be declared">; +def err_out_of_line_type_names_constructor : Error< + "qualified reference to %0 is a constructor name rather than a " + "type wherever a constructor can be declared">; + +def err_expected_qualified_after_typename : Error< + "expected a qualified name after 'typename'">; +def err_expected_semi_after_tagdecl : Error< + "expected ';' after %0">; + +def err_typename_refers_to_non_type_template : Error< + "typename specifier refers to a non-template">; +def err_expected_type_name_after_typename : Error< + "expected an identifier or template-id after '::'">; +def err_explicit_spec_non_template : Error< + "explicit %select{specialization|instantiation}0 of non-template " + "%select{class|struct|union}1 %2">; + +def err_variadic_templates : Error< + "variadic templates are only allowed in C++0x">; + +def err_default_template_template_parameter_not_template : Error< + "default template argument for a template template parameter must be a class " + "template">; + +// C++ declarations +def err_friend_decl_defines_class : Error< + "cannot define a type in a friend declaration">; + +// Language specific pragmas +// - Generic warnings +def warn_pragma_expected_lparen : Warning< + "missing '(' after '#pragma %0' - ignoring">; +def warn_pragma_expected_rparen : Warning< + "missing ')' after '#pragma %0' - ignoring">; +def warn_pragma_expected_identifier : Warning< + "expected identifier in '#pragma %0' - ignored">; +def warn_pragma_extra_tokens_at_eol : Warning< + "extra tokens at end of '#pragma %0' - ignored">; +// - #pragma options +def warn_pragma_options_expected_align : Warning< + "expected 'align' following '#pragma options' - ignored">; +def warn_pragma_options_expected_equal : Warning< + "expected '=' following '#pragma options align' - ignored">; +def warn_pragma_options_invalid_option : Warning< + "invalid alignment option in '#pragma options align' - ignored">; +// - #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 +def warn_pragma_unused_expected_var : Warning< + "expected '#pragma unused' argument to be a variable name">; +def warn_pragma_unused_expected_punc : Warning< + "expected ')' or ',' in '#pragma unused'">; + +} // end of Parse Issue category. +} // end of Parser diagnostics diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td new file mode 100644 index 0000000..0ba31ae --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -0,0 +1,3100 @@ +//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Semantic Analysis +//===----------------------------------------------------------------------===// + +let Component = "Sema" in { +let CategoryName = "Semantic Issue" in { + +// Constant expressions +def err_expr_not_ice : Error< + "expression is not an integer constant expression">; +def ext_expr_not_ice : Extension< + "expression is not integer constant expression " + "(but is allowed as an extension)">; + +def ext_null_pointer_expr_not_ice : Extension< + "null pointer expression is not an integer constant expression " + "(but is allowed as an extension)">; + + + +// Semantic analysis of constant literals. +def ext_predef_outside_function : Warning< + "predefined identifier is only valid inside function">; +def warn_float_overflow : Warning< + "magnitude of floating-point constant too large for type %0; maximum is %1">, + InGroup<LiteralRange>; +def warn_float_underflow : Warning< + "magnitude of floating-point constant too small for type %0; minimum is %1">, + InGroup<LiteralRange>; + +// C99 variable-length arrays +def ext_vla : Extension< + "variable length arrays are a C99 feature, accepted as an extension">, + InGroup<VLA>; +def err_vla_non_pod : Error<"variable length array of non-POD element type %0">; +def err_vla_in_sfinae : Error< + "variable length array cannot be formed during template argument deduction">; +def err_array_star_in_function_definition : Error< + "variable length array must be bound in function definition">; +def err_vla_decl_in_file_scope : Error< + "variable length array declaration not allowed at file scope">; +def err_vla_decl_has_static_storage : Error< + "variable length array declaration can not have 'static' storage duration">; +def err_vla_decl_has_extern_linkage : Error< + "variable length array declaration can not have 'extern' linkage">; + +// C99 variably modified types +def err_variably_modified_template_arg : Error< + "variably modified type %0 cannot be used as a template argument">; +def err_variably_modified_nontype_template_param : Error< + "non-type template parameter of variably modified type %0">; + +// C99 Designated Initializers +def err_array_designator_negative : Error< + "array designator value '%0' is negative">; +def err_array_designator_empty_range : Error< + "array designator range [%0, %1] is empty">; +def err_array_designator_non_array : Error< + "array designator cannot initialize non-array type %0">; +def err_array_designator_too_large : Error< + "array designator index (%0) exceeds array bounds (%1)">; +def err_field_designator_non_aggr : Error< + "field designator cannot initialize a " + "%select{non-struct, non-union|non-class}0 type %1">; +def err_field_designator_unknown : Error< + "field designator %0 does not refer to any field in type %1">; +def err_field_designator_nonfield : Error< + "field designator %0 does not refer to a non-static data member">; +def note_field_designator_found : Note<"field designator refers here">; +def err_designator_for_scalar_init : Error< + "designator in initializer for scalar type %0">; +def warn_subobject_initializer_overrides : Warning< + "subobject initialization overrides initialization of other fields " + "within its enclosing subobject">; +def warn_initializer_overrides : Warning< + "initializer overrides prior initialization of this subobject">; +def note_previous_initializer : Note< + "previous initialization %select{|with side effects }0is here" + "%select{| (side effects may not occur at run time)}0">; +def err_designator_into_flexible_array_member : Error< + "designator into flexible array member subobject">; +def note_flexible_array_member : Note< + "initialized flexible array member %0 is here">; +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_parameter_name_omitted : Error<"parameter name omitted">; +def warn_unused_parameter : Warning<"unused parameter %0">, + InGroup<UnusedParameter>, DefaultIgnore; +def warn_unused_variable : Warning<"unused variable %0">, + InGroup<UnusedVariable>, DefaultIgnore; +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">; +def warn_unused_function : Warning<"unused function %0">, + InGroup<UnusedFunction>, DefaultIgnore; + +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 err_ellipsis_first_arg : Error< + "ISO C requires a named argument before '...'">; +def err_declarator_need_ident : Error<"declarator requires an identifier">; +def err_bad_language : Error<"unknown linkage language">; +def warn_use_out_of_scope_declaration : Warning< + "use of out-of-scope declaration of %0">; +def err_inline_non_function : Error< + "'inline' can only appear on functions">; + +def warn_decl_shadow : + Warning<"declaration shadows a %select{" + "local variable|" + "variable in %2|" + "static data member of %2|" + "field of %2}1">, + InGroup<Shadow>, DefaultIgnore; + +// C++ using declarations +def err_using_requires_qualname : Error< + "using declaration requires a qualified name">; +def err_using_typename_non_type : Error< + "'typename' keyword used on a non-type">; +def err_using_dependent_value_is_type : Error< + "dependent using declaration resolved to type without 'typename'">; +def err_using_decl_nested_name_specifier_is_not_class : Error< + "using declaration in class refers into '%0', which is not a class">; +def err_using_decl_nested_name_specifier_is_current_class : Error< + "using declaration refers to its own class">; +def err_using_decl_nested_name_specifier_is_not_base_class : Error< + "using declaration refers into '%0', which is not a base class of %1">; +def err_using_decl_can_not_refer_to_class_member : Error< + "using declaration can not refer to class member">; +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 err_using_decl_destructor : Error< + "using declaration can not refer to a destructor">; +def err_using_decl_template_id : Error< + "using declaration can not refer to a template specialization">; +def note_using_decl_target : Note<"target of using declaration">; +def note_using_decl_conflict : Note<"conflicting declaration">; +def err_using_decl_redeclaration : Error<"redeclaration of using decl">; +def err_using_decl_conflict : Error< + "target of using declaration conflicts with declaration already in scope">; +def err_using_decl_conflict_reverse : Error< + "declaration conflicts with target of using declaration already in scope">; +def note_using_decl : Note<"%select{|previous }0using declaration">; + +def warn_access_decl_deprecated : Warning< + "access declarations are deprecated; use using declarations instead">, + InGroup<Deprecated>; + +def err_invalid_thread : Error< + "'__thread' is only allowed on variable declarations">; +def err_thread_non_global : Error< + "'__thread' variables must have global storage">; +def err_thread_unsupported : Error< + "thread-local storage is unsupported for the current target">; + +def warn_maybe_falloff_nonvoid_function : Warning< + "control may reach end of non-void function">, + InGroup<ReturnType>; +def warn_falloff_nonvoid_function : Warning< + "control reaches end of non-void function">, + InGroup<ReturnType>; +def err_maybe_falloff_nonvoid_block : Error< + "control may reach end of non-void block">; +def err_falloff_nonvoid_block : Error< + "control reaches end of non-void block">; +def warn_suggest_noreturn_function : Warning< + "function could be attribute 'noreturn'">, + InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; +def warn_suggest_noreturn_block : Warning< + "block could be attribute 'noreturn'">, + InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; +def warn_unreachable : Warning<"will never be executed">, + InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore; + +/// Built-in functions. +def ext_implicit_lib_function_decl : ExtWarn< + "implicitly declaring C library function '%0' with type %1">; +def note_please_include_header : Note< + "please include the header <%0> or explicitly provide a " + "declaration for '%1'">; +def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; +def err_implicit_decl_requires_stdio : Error< + "implicit declaration of '%0' requires inclusion of the header <stdio.h>">; +def err_implicit_decl_requires_setjmp : Error< + "implicit declaration of '%0' requires inclusion of the header <setjmp.h>">; +def warn_redecl_library_builtin : Warning< + "incompatible redeclaration of library function %0">; +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; + +/// main() +// static/inline main() are not errors in C, just in C++. +def warn_unusual_main_decl : Warning<"'main' should not be declared " + "%select{static|inline|static or inline}0">; +def err_unusual_main_decl : Error<"'main' is not allowed to be declared " + "%select{static|inline|static or inline}0">; +def err_main_returns_nonint : Error<"'main' must return 'int'">; +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">; +def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " + "parameter of 'main' (%select{argument count|argument array|environment|" + "platform-specific data}0) must be of type %1">; + +/// parser diagnostics +def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; +def err_statically_allocated_object : Error< + "interface type cannot be statically allocated">; +def err_object_cannot_be_passed_returned_by_value : Error< + "interface type %1 cannot be %select{returned|passed}0 by value" + "; did you forget * in %1">; +def warn_enum_value_overflow : Warning<"overflow in enumeration value">; +def warn_pragma_options_align_unsupported_option : Warning< + "unsupported alignment option in '#pragma options align'">; +def warn_pragma_options_align_reset_failed : Warning< + "#pragma options align=reset failed: %0">; +def err_pragma_options_align_mac68k_target_unsupported : Error< + "mac68k alignment pragma is not supported on this target">; +def warn_pragma_pack_invalid_alignment : Warning< + "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">; +// Follow the MSVC implementation. +def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">; +def warn_pragma_pack_pop_identifer_and_alignment : Warning< + "specifying both a name and alignment to 'pop' is undefined">; +def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">; + +def warn_pragma_unused_undeclared_var : Warning< + "undeclared variable %0 used as an argument for '#pragma unused'">; +def warn_pragma_unused_expected_localvar : Warning< + "only local 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">; + +/// Objective-C parser diagnostics +def err_duplicate_class_def : Error< + "duplicate interface definition for class %0">; +def err_undef_superclass : Error< + "cannot find interface declaration for %0, superclass of %1">; +def err_no_nsconstant_string_class : Error< + "cannot find interface declaration for %0">; +def err_recursive_superclass : Error< + "trying to recursively use %0 as superclass of %1">; +def warn_previous_alias_decl : Warning<"previously declared alias is ignored">; +def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">; +def warn_undef_interface : Warning<"cannot find interface declaration for %0">; +def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">; +def err_protocol_has_circular_dependency : Error< + "protocol has circular dependency">; +def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">; +def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">; +def warn_readonly_property : Warning< + "attribute 'readonly' of property %0 restricts attribute " + "'readwrite' of property inherited from %1">; + +def warn_property_attribute : Warning< + "property %0 '%1' attribute does not match the property inherited from %2">; +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_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 warn_dup_category_def : Warning< + "duplicate definition of category %1 on interface %0">; +def err_conflicting_super_class : Error<"conflicting super class name %0">; +def err_dup_implementation_class : Error<"reimplementation of class %0">; +def err_dup_implementation_category : Error< + "reimplementation of category %1 for class %0">; +def err_conflicting_ivar_type : Error< + "instance variable %0 has conflicting type: %1 vs %2">; +def err_duplicate_ivar_declaration : Error< + "instance variable is already declared">; +def warn_on_superclass_use : Warning< + "class implementation may not have super class">; +def err_conflicting_ivar_bitwidth : Error< + "instance variable %0 has conflicting bit-field width">; +def err_conflicting_ivar_name : Error< + "conflicting instance variable names: %0 vs %1">; +def err_inconsistant_ivar_count : Error< + "inconsistent number of instance variables specified">; +def warn_incomplete_impl : Warning<"incomplete implementation">; +def note_undef_method_impl : Note<"method definition for %0 not found">; +def note_required_for_protocol_at : + Note<"required for direct or indirect protocol %0">; + +def warn_conflicting_ret_types : Warning< + "conflicting return type in implementation of %0: %1 vs %2">; + +def warn_conflicting_param_types : Warning< + "conflicting parameter types in implementation of %0: %1 vs %2">; +def warn_conflicting_variadic :Warning< + "conflicting variadic declaration of method and its implementation">; + +def warn_implements_nscopying : Warning< +"default assign attribute on property %0 which implements " +"NSCopying protocol is not appropriate with -fobjc-gc[-only]">; + +def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; +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 err_setter_type_void : Error<"type of setter must be void">; +def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; +def warn_missing_atend : Warning<"'@end' is missing in implementation context">; +def err_objc_var_decl_inclass : + Error<"cannot declare variable inside @interface or @protocol">; +def error_missing_method_context : Error< + "missing context for method declaration">; +def err_objc_property_attr_mutually_exclusive : Error< + "property attributes '%0' and '%1' are mutually exclusive">; +def err_objc_property_requires_object : Error< + "property with '%0' attribute must be of object type">; +def warn_objc_property_no_assignment_attribute : Warning< + "no 'assign', 'retain', or 'copy' attribute is specified - " + "'assign' is assumed">; +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< + "property attribute in continuation class does not match the primary class">; +def warn_objc_property_copy_missing_on_block : Warning< + "'copy' attribute must be specified for the block property " + "when -fobjc-gc-only is specified">; +def warn_atomic_property_rule : Warning< + "writable atomic property %0 cannot pair a synthesized setter/getter " + "with a user defined setter/getter">; +def err_use_continuation_class : Error< + "illegal declaration of property in continuation class %0" + ": attribute must be readwrite, while its primary must be readonly">; +def err_continuation_class : Error<"continuation class has no primary class">; +def err_property_type : Error<"property cannot have array or function type %0">; +def error_missing_property_context : Error< + "missing context for property implementation declaration">; +def error_bad_property_decl : Error< + "property implementation must have its declaration in interface %0">; +def error_category_property : Error< + "property declared in category %0 cannot be implemented in " + "class implementation">; +def note_property_declare : Note< + "property declared here">; +def error_synthesize_category_decl : Error< + "@synthesize not allowed in a category's implementation">; +def error_reference_property : Error< + "property of reference type is not supported">; +def error_missing_property_interface : Error< + "property implementation in a category with no category declaration">; +def error_bad_category_property_decl : Error< + "property implementation must have its declaration in the category %0">; +def error_bad_property_context : Error< + "property implementation must be in a class or category implementation">; +def error_missing_property_ivar_decl : Error< + "synthesized property %0 must either be named the same as a compatible" + " ivar or must explicitly name an ivar">; + +def error_synthesized_ivar_yet_not_supported : Error< + "instance variable synthesis not yet supported" + " (need to declare %0 explicitly)">; + +def error_property_ivar_type : Error< + "type of property %0 (%1) does not match type of ivar %2 (%3)">; +def error_ivar_in_superclass_use : Error< + "property %0 attempting to use ivar %1 declared in super class %2">; +def error_weak_property : Error< + "existing ivar %1 for __weak property %0 must be __weak">; +def error_strong_property : Error< + "existing ivar %1 for a __strong property %0 must be garbage collectable">; +def error_dynamic_property_ivar_decl : Error< + "dynamic property can not have ivar specification">; +def error_duplicate_ivar_use : Error< + "synthesized properties %0 and %1 both claim ivar %2">; +def error_property_implemented : Error<"property %0 is already implemented">; +def warn_objc_property_attr_mutually_exclusive : Warning< + "property attributes '%0' and '%1' are mutually exclusive">, + InGroup<ReadOnlySetterAttrs>, DefaultIgnore; +def warn_undeclared_selector : Warning< + "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; +def warn_unimplemented_protocol_method : Warning< + "method 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_unexpected_friend : Error< + "friends can only be classes or functions">; +def ext_enum_friend : ExtWarn< + "enumeration type %0 cannot be a friend">; +def ext_nonclass_type_friend : ExtWarn< + "non-class type %0 cannot be a friend">; +def err_friend_is_member : Error< + "friends cannot be members of the declaring class">; +def ext_unelaborated_friend_type : ExtWarn< + "must specify '%select{struct|union|class|enum}0' to befriend %1">; +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< + "must use a qualified name when declaring a %select{constructor|" + "destructor|conversion operator}0 as a friend">; +def err_tagless_friend_type_template : Error< + "friend type templates must use an elaborated type">; + +def err_abstract_type_in_decl : Error< + "%select{return|parameter|variable|field}0 type %1 is an abstract class">; +def err_allocation_of_abstract_type : Error< + "allocation of an object of abstract type %0">; +def err_throw_abstract_type : Error< + "cannot throw an object of abstract type %0">; +def err_array_of_abstract_type : Error<"array of abstract class type %0">; + +def err_multiple_final_overriders : Error< + "virtual function %q0 has more than one final overrider in %1">; +def note_final_overrider : Note<"final overrider of %q0 in %1">; + +def err_type_defined_in_type_specifier : Error< + "%0 can not be defined in a type specifier">; +def err_type_defined_in_result_type : Error< + "%0 can not be defined in the result type of a function">; +def err_type_defined_in_param_type : Error< + "%0 can not be defined in a parameter type">; + +def note_pure_virtual_function : Note< + "pure virtual function %0">; + +def err_deleted_non_function : Error< + "only functions can have deleted definitions">; +def err_deleted_decl_not_first : Error< + "deleted definition must be first declaration">; + +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; + +// C++ exception specifications +def err_exception_spec_in_typedef : Error< + "exception specifications are not allowed in typedefs">; +def err_distant_exception_spec : Error< + "exception specifications are not allowed beyond a single level " + "of indirection">; +def err_incomplete_in_exception_spec : Error< + "%select{|pointer to |reference to }0incomplete type %1 is not allowed " + "in exception specification">; +def err_mismatched_exception_spec : Error< + "exception specification in declaration does not match previous declaration">; +def err_override_exception_spec : Error< + "exception specification of overriding function is more lax than " + "base version">; +def err_incompatible_exception_specs : Error< + "target exception specification is not superset of source">; +def err_deep_exception_specs_differ : Error< + "exception specifications of %select{return|argument}0 types differ">; +def warn_missing_exception_specification : Warning< + "%0 is missing exception specification '%1'">; + +// C++ access checking +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">, NoSFINAE; +def err_access_ctor : Error< + "calling a %select{private|protected}0 constructor of class %2">, NoSFINAE; +def err_access_base : Error< + "%select{base class|inherited virtual base class}0 %1 has %select{private|" + "protected}3 %select{constructor|copy constructor|copy assignment operator|" + "destructor}2">, NoSFINAE; +def err_access_field: Error< + "field of type %0 has %select{private|protected}2 %select{constructor|copy " + "constructor|copy assignment operator|destructor}1">, NoSFINAE; + +def err_access_ctor_field : + Error<"field of type %1 has %select{private|protected}2 constructor">, + NoSFINAE; +def err_access_dtor_base : + Error<"base class %0 has %select{private|protected}1 destructor">, + NoSFINAE; +def err_access_dtor_vbase : + Error<"inherited virtual base class %0 has " + "%select{private|protected}1 destructor">, + NoSFINAE; +def err_access_dtor_temp : + Error<"temporary of type %0 has %select{private|protected}1 destructor">, + NoSFINAE; +def err_access_dtor_field : + Error<"field of type %1 has %select{private|protected}2 destructor">, + NoSFINAE; +def err_access_dtor_var : + Error<"variable of type %1 has %select{private|protected}2 destructor">, + NoSFINAE; +def err_access_assign_field : + Error<"field of type %1 has %select{private|protected}2 copy assignment" + " operator">, + NoSFINAE; +def err_access_assign_base : + Error<"base class %0 has %select{private|protected}1 copy assignment" + " operator">, + NoSFINAE; +def err_access_copy_field : + Error<"field of type %1 has %select{private|protected}2 copy constructor">, + NoSFINAE; +def err_access_copy_base : + Error<"base class %0 has %select{private|protected}1 copy constructor">, + NoSFINAE; +def err_access_dtor_ivar : + Error<"instance variable of type %0 has %select{private|protected}1 " + "destructor">, + NoSFINAE; +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">; +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">; + +// C++ name lookup +def err_incomplete_nested_name_spec : Error< + "incomplete type %0 named in nested name specifier">; +def err_dependent_nested_name_spec : Error< + "nested name specifier for a declaration cannot depend on a template " + "parameter">; +def err_nested_name_member_ref_lookup_ambiguous : Error< + "lookup of %0 in member access expression is ambiguous">; +def note_ambig_member_ref_object_type : Note< + "lookup in the object type %0 refers here">; +def note_ambig_member_ref_scope : Note< + "lookup from the current scope refers here">; +def err_qualified_member_nonclass : Error< + "qualified member access refers to a member in %0">; +def err_incomplete_member_access : Error< + "member access into incomplete type %0">; +def err_incomplete_type : Error< + "incomplete type %0 where a complete type is required">; + +// C++ class members +def err_storageclass_invalid_for_member : Error< + "storage class specified for a member declaration">; +def err_mutable_function : Error<"'mutable' cannot be applied to functions">; +def err_mutable_reference : Error<"'mutable' cannot be applied to references">; +def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">; +def err_mutable_nonmember : Error< + "'mutable' can only be applied to member variables">; +def err_virtual_non_function : Error< + "'virtual' can only appear on non-static member functions">; +def err_virtual_out_of_class : Error< + "'virtual' can only be specified inside the class definition">; +def err_explicit_non_function : Error< + "'explicit' can only appear on non-static member functions">; +def err_explicit_out_of_class : Error< + "'explicit' can only be specified inside the class definition">; +def err_explicit_non_ctor_or_conv_function : Error< + "'explicit' can only be applied to a constructor or conversion function">; +def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">; +def err_static_out_of_line : Error< + "'static' can only be specified inside the class definition">; +def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">; +def err_not_integral_type_bitfield : Error< + "bit-field %0 has non-integral type %1">; +def err_not_integral_type_anon_bitfield : Error< + "anonymous bit-field has non-integral type %0">; +def err_member_initialization : Error< + "%0 can only be initialized if it is a static const integral data member">; +def err_member_function_initialization : Error< + "initializer on function does not look like a pure-specifier">; +def err_non_virtual_pure : Error< + "%0 is not virtual and cannot be declared pure">; +def err_implicit_object_parameter_init : Error< + "cannot initialize object parameter of type %0 with an expression " + "of type %1">; +def err_qualified_member_of_unrelated : Error< + "%q0 is not a member of class %1">; + +def note_field_decl : Note<"member is declared here">; +def note_ivar_decl : Note<"ivar is declared here">; +def note_bitfield_decl : Note<"bit-field is declared here">; +def note_previous_decl : Note<"%0 declared here">; +def note_member_synthesized_at : Note< + "implicit default %select{constructor|copy constructor|" + "copy assignment operator|destructor}0 for %1 first required here">; +def err_missing_default_ctor : Error< + "%select{|implicit default }0constructor for %1 must explicitly initialize " + "the %select{base class|member}2 %3 which does not have a default " + "constructor">; +def err_illegal_union_member : Error< + "union member %0 has a non-trivial %select{constructor|" + "copy constructor|copy assignment operator|destructor}1">; +def note_nontrivial_has_virtual : Note< + "because type %0 has a virtual %select{member function|base class}1">; +def note_nontrivial_has_nontrivial : Note< + "because type %0 has a %select{member|base class}1 with a non-trivial " + "%select{constructor|copy constructor|copy assignment operator|destructor}2">; +def note_nontrivial_user_defined : Note< + "because type %0 has a user-declared %select{constructor|copy constructor|" + "copy assignment operator|destructor}1">; + +def err_different_return_type_for_overriding_virtual_function : Error< + "virtual function %0 has a different return type (%1) than the " + "function it overrides (which has return type %2)">; +def note_overridden_virtual_function : Note< + "overridden virtual function is here">; + +def err_covariant_return_inaccessible_base : Error< + "invalid covariant return for virtual function: %1 is a " + "%select{private|protected}2 base class of %0">, NoSFINAE; +def err_covariant_return_ambiguous_derived_to_base_conv : Error< + "return type of virtual function %3 is not covariant with the return type of " + "the function it overrides (ambiguous conversion from derived class " + "%0 to base class %1:%2)">; +def err_covariant_return_not_derived : Error< + "return type of virtual function %0 is not covariant with the return type of " + "the function it overrides (%1 is not derived from %2)">; +def err_covariant_return_incomplete : Error< + "return type of virtual function %0 is not covariant with the return type of " + "the function it overrides (%1 is incomplete)">; +def err_covariant_return_type_different_qualifications : Error< + "return type of virtual function %0 is not covariant with the return type of " + "the function it overrides (%1 has different qualifiers than %2)">; +def err_covariant_return_type_class_type_more_qualified : Error< + "return type of virtual function %0 is not covariant with the return type of " + "the function it overrides (class type %1 is more qualified than class " + "type %2">; + +// C++ constructors +def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">; +def err_invalid_qualified_constructor : Error< + "'%0' qualifier is not allowed on a constructor">; +def err_constructor_return_type : Error< + "constructor cannot have a return type">; +def err_constructor_redeclared : Error<"constructor cannot be redeclared">; +def err_constructor_byvalue_arg : Error< + "copy constructor must pass its first argument by reference">; +def warn_no_constructor_for_refconst : Warning< + "%select{struct|union|class|enum}0 %1 does not declare any constructor to " + "initialize its non-modifiable members">; +def note_refconst_member_not_initialized : Note< + "%select{const|reference}0 member %1 will never be initialized">; + +// C++ destructors +def err_destructor_not_member : Error< + "destructor must be a non-static member function">; +def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">; +def err_invalid_qualified_destructor : Error< + "'%0' qualifier is not allowed on a destructor">; +def err_destructor_return_type : Error<"destructor cannot have a return type">; +def err_destructor_redeclared : Error<"destructor cannot be redeclared">; +def err_destructor_with_params : Error<"destructor cannot have any parameters">; +def err_destructor_variadic : Error<"destructor cannot be variadic">; +def err_destructor_typedef_name : Error< + "destructor cannot be declared using a typedef %0 of the class name">; +def err_destructor_name : Error< + "expected the class name after '~' to name the enclosing class">; +def err_destructor_class_name : Error< + "expected the class name after '~' to name a destructor">; +def err_ident_in_pseudo_dtor_not_a_type : Error< + "identifier %0 in pseudo-destructor expression does not name a type">; + +// C++ initialization +def err_init_conversion_failed : Error< + "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 vector element}0 of type %1 with an %select{rvalue|lvalue}2 of " + "type %3">; + +def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">; +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_temporary : Error< + "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " + "temporary of type %2">; +def err_lvalue_reference_bind_to_unrelated : Error< + "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " + "value of unrelated type %2">; +def err_reference_bind_drops_quals : Error< + "binding of reference to type %0 to a value of type %1 drops qualifiers">; +def err_reference_bind_failed : Error< + "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type " + "%2">; +def err_reference_bind_init_list : Error< + "reference to type %0 cannot bind to an initializer list">; +def err_init_list_bad_dest_type : Error< + "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " + "list">; + +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< + "reference cannot be initialized with multiple values">; +def err_init_non_aggr_init_list : Error< + "initialization of non-aggregate type %0 with an initializer list">; +def err_init_reference_member_uninitialized : Error< + "reference member of type %0 uninitialized">; +def note_uninit_reference_member : Note< + "uninitialized reference member is here">; +def warn_field_is_uninit : Warning<"field is uninitialized when used here">, + InGroup<DiagGroup<"uninitialized">>; +def err_init_incomplete_type : Error<"initialization of incomplete type %0">; + +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">; +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">; +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">; +def err_temp_copy_incomplete : Error< + "copying a temporary object of incomplete type %0">; + +// C++0x decltype +def err_cannot_determine_declared_type_of_overloaded_function : Error< + "cannot determine the %select{type|declared type}0 of an overloaded " + "function">; + +// C++0x auto +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< + "'%0' declared as array of 'auto'">; +def err_auto_not_allowed : Error< + "'auto' not allowed in %select{function prototype|struct member|union member" + "|class member|exception declaration|template parameter|block literal}0">; +def err_auto_var_requires_init : Error< + "declaration of variable %0 with type %1 requires an initializer">; + +// C++0x attributes +def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; + +// C++0x [[final]] +def err_final_function_overridden : Error< + "declaration of %0 overrides a 'final' function">; +def err_final_base : Error< + "derivation from 'final' %0">; + +// Objective-C++ +def err_objc_decls_may_only_appear_in_global_scope : Error< + "Objective-C declarations may only appear in global scope">; +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< + "%0 and %1 attributes are not compatible">; +def err_attribute_wrong_number_arguments : Error< + "attribute requires %0 argument(s)">; +def err_attribute_missing_parameter_name : Error< + "attribute requires unquoted parameter">; +def err_attribute_invalid_vector_type : Error<"invalid vector type %0">; +def err_attribute_argument_not_int : Error< + "'%0' attribute requires integer constant">; +def err_attribute_argument_n_not_int : Error< + "'%0' attribute requires parameter %1 to be an integer constant">; +def err_attribute_argument_n_not_string : Error< + "'%0' attribute requires parameter %1 to be a string">; +def err_attribute_argument_out_of_bounds : Error< + "'%0' attribute parameter %1 is out of bounds">; +def err_attribute_requires_objc_interface : Error< + "attribute may only be applied to an Objective-C interface">; +def err_nonnull_pointers_only : Error< + "nonnull attribute only applies to pointer arguments">; +def err_format_strftime_third_parameter : Error< + "strftime format attribute requires 3rd parameter to be 0">; +def err_format_attribute_requires_variadic : Error< + "format attribute requires variadic function">; +def err_format_attribute_not : Error<"format argument not %0">; +def err_format_attribute_result_not : Error<"function does not return %0">; +def err_attribute_invalid_size : Error< + "vector size not an integral multiple of component size">; +def err_attribute_zero_size : Error<"zero vector size">; +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< + "illegal vector component name '%0'">; +def err_attribute_address_space_not_int : Error< + "address space attribute requires an integer constant">; +def err_attribute_address_space_negative : Error< + "address space is negative">; +def err_attribute_address_space_too_high : Error< + "address space is larger than the maximum supported (%0)">; +def err_attribute_address_multiple_qualifiers : Error< + "multiple address spaces specified for type">; +def err_implicit_pointer_address_space_cast : Error< + "illegal implicit cast between two pointers with different address spaces">; +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_attribute_not_string : Error< + "argument to %0 attribute was not a string literal">; +def err_attribute_section_invalid_for_target : Error< + "argument to 'section' attribute is not valid for this target: %0">; +def err_attribute_section_local_variable : Error< + "'section' attribute is not valid on local variables">; +def err_attribute_aligned_not_power_of_two : Error< + "requested alignment is not a power of 2">; +def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< + "'%0' redeclared without %1 attribute: previous %1 ignored">; +def warn_attribute_ignored : Warning<"%0 attribute ignored">; +def warn_attribute_precede_definition : Warning< + "attribute declaration must precede definition">; +def warn_attribute_void_function_method : Warning< + "attribute %0 cannot be applied to " + "%select{functions|Objective-C method}1 without return value">; +def warn_attribute_weak_on_field : Warning< + "__weak attribute cannot be specified on a field declaration">; +def warn_attribute_weak_on_local : Warning< + "__weak attribute cannot be specified on an automatic variable">; +def warn_weak_identifier_undeclared : Warning< + "weak identifier %0 never declared">; +def err_attribute_weak_static : Error< + "weak declaration of '%0' must be public">; +def warn_attribute_weak_import_invalid_on_definition : Warning< + "'weak_import' attribute cannot be specified on a definition">; +def err_attribute_weakref_not_static : Error< + "weakref declaration of '%0' must be static">; +def err_attribute_weakref_not_global_context : Error< + "weakref declaration of '%0' must be in a global context">; +def err_attribute_weakref_without_alias : Error< + "weakref declaration of '%0' must also have an alias attribute">; +def warn_attribute_wrong_decl_type : Warning< + "%0 attribute only applies to %select{function|union|" + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter|class|virtual method" + "|member}1 types">; +def err_attribute_wrong_decl_type : Error< + "%0 attribute only applies to %select{function|union|" + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter|class|virtual method" + "|member}1 types">; +def warn_function_attribute_wrong_type : Warning< + "%0 only applies to function types; type here is %1">; +def warn_gnu_inline_attribute_requires_inline : Warning< + "'gnu_inline' attribute requires function to be marked 'inline'," + " attribute ignored">; +def err_cconv_change : Error< + "function declared '%0' here was previously declared " + "%select{'%2'|without calling convention}1">; +def err_cconv_knr : Error< + "function with no prototype cannot use %0 calling convention">; +def err_cconv_varargs : Error< + "variadic function cannot use %0 calling convention">; + +def warn_impcast_vector_scalar : Warning< + "implicit cast turns vector to scalar: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_complex_scalar : Warning< + "implicit cast discards imaginary component: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_float_precision : Warning< + "implicit cast loses floating-point precision: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_float_integer : Warning< + "implicit cast turns floating-point number into integer: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_sign : Warning< + "implicit cast changes signedness: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_sign_conditional : Warning< + "operand of ? changes signedness: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_precision : Warning< + "implicit cast loses integer precision: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_64_32 : Warning< + "implicit cast loses integer precision: %0 to %1">, + InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; + +def warn_attribute_ignored_for_field_of_type : Warning< + "%0 attribute ignored for field of type %1">; +def warn_transparent_union_attribute_field_size_align : Warning< + "%select{alignment|size}0 of field %1 (%2 bits) does not match the " + "%select{alignment|size}0 of the first field in transparent union; " + "transparent_union attribute ignored">; +def note_transparent_union_first_field_size_align : Note< + "%select{alignment|size}0 of first field is %1 bits">; +def warn_transparent_union_attribute_not_definition : Warning< + "transparent_union attribute can only be applied to a union definition; " + "attribute ignored">; +def warn_transparent_union_attribute_floating : Warning< + "first field of a transparent union cannot have floating point or vector " + "type; transparent_union attribute ignored">; +def warn_transparent_union_attribute_zero_fields : Warning< + "transparent union definition must contain at least one field; " + "transparent_union attribute ignored">; +def warn_attribute_type_not_supported : Warning< + "'%0' attribute argument not supported: %1">; +def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">; +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< + "mode attribute only supported for integer and floating-point types">; +def err_mode_wrong_type : Error< + "type of machine mode does not match type of base type">; +def err_attr_wrong_decl : Error< + "'%0' attribute invalid on this declaration, requires typedef or value">; +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< + "'sentinel' attribute only supported for variadic %select{functions|blocks}0">; +def err_attribute_sentinel_less_than_zero : Error< + "'sentinel' parameter 1 less than zero">; +def err_attribute_sentinel_not_zero_or_one : Error< + "'sentinel' parameter 2 not 0 or 1">; +def err_attribute_cleanup_arg_not_found : Error< + "'cleanup' argument %0 not found">; +def err_attribute_cleanup_arg_not_function : Error< + "'cleanup' argument %0 is not a function">; +def err_attribute_cleanup_func_must_take_one_arg : Error< + "'cleanup' function %0 must take 1 parameter">; +def err_attribute_cleanup_func_arg_incompatible_type : Error< + "'cleanup' function %0 parameter has type %1 which is incompatible with " + "type %2">; +def err_attribute_regparm_wrong_platform : Error< + "'regparm' is not valid on this platform">; +def err_attribute_regparm_invalid_number : Error< + "'regparm' parameter must be between 0 and %0 inclusive">; + + +// Clang-Specific Attributes +def err_attribute_iboutlet : Error< + "%0 attribute can only be applied to instance variables or properties">; +def err_attribute_ibaction: Error< + "ibaction attribute can only be applied to Objective-C instance methods">; +def err_attribute_overloadable_not_function : Error< + "'overloadable' attribute can only be applied to a function">; +def err_attribute_overloadable_missing : Error< + "%select{overloaded function|redeclaration of}0 %1 must have the " + "'overloadable' attribute">; +def note_attribute_overloadable_prev_overload : Note< + "previous overload of function is here">; +def err_attribute_overloadable_no_prototype : Error< + "'overloadable' function %0 must have a prototype">; +def warn_ns_attribute_wrong_return_type : Warning< + "%0 attribute only applies to functions or methods that " + "return a pointer or Objective-C object">; + +// Function Parameter Semantic Analysis. +def err_param_with_void_type : Error<"argument may not have 'void' type">; +def err_void_only_param : Error< + "'void' must be the first and only parameter if specified">; +def err_void_param_qualified : Error< + "'void' as parameter must not have type qualifiers">; +def err_ident_list_in_fn_declaration : Error< + "a parameter list without types is only allowed in a function definition">; +def ext_param_not_declared : Extension< + "parameter %0 was not declared, defaulting to type 'int'">; +def err_param_typedef_of_void : Error< + "empty parameter list defined with a typedef of 'void' not allowed in C++">; +def err_param_default_argument : Error< + "C does not support default arguments">; +def err_param_default_argument_redefinition : Error< + "redefinition of default argument">; +def err_param_default_argument_missing : Error< + "missing default argument on parameter">; +def err_param_default_argument_missing_name : Error< + "missing default argument on parameter %0">; +def err_param_default_argument_references_param : Error< + "default argument references parameter %0">; +def err_param_default_argument_references_local : Error< + "default argument references local variable %0 of enclosing function">; +def err_param_default_argument_references_this : Error< + "default argument references 'this'">; +def err_param_default_argument_nonfunc : Error< + "default arguments can only be specified for parameters in a function " + "declaration">; +def err_param_default_argument_template_redecl : Error< + "default arguments cannot be added to a function template that has already " + "been declared">; +def err_param_default_argument_member_template_redecl : Error< + "default arguments cannot be added to an out-of-line definition of a member " + "of a %select{class template|class template partial specialization|nested " + "class in a template}0">; +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">; + +def err_use_of_default_argument_to_function_declared_later : Error< + "use of default argument to function %0 that is declared later in class %1">; +def note_default_argument_declared_here : Note< + "default argument declared here">; + +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">; + + +// C++ Overloading Semantic Analysis. +def err_ovl_diff_return_type : Error< + "functions that differ only in their return type cannot be overloaded">; +def err_ovl_static_nonstatic_member : Error< + "static and non-static member functions with the same parameter types " + "cannot be overloaded">; + +def err_ovl_no_viable_function_in_call : Error< + "no matching function for call to %0">; +def err_ovl_no_viable_member_function_in_call : Error< + "no matching member function for call to %0">; +def err_ovl_ambiguous_call : Error< + "call to %0 is ambiguous">; +def err_ovl_deleted_call : Error< + "call to %select{unavailable|deleted}0 function %1">; +def err_ovl_ambiguous_member_call : Error< + "call to member function %0 is ambiguous">; +def err_ovl_deleted_member_call : Error< + "call to %select{unavailable|deleted}0 member function %1">; +def note_ovl_candidate : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "is the implicit default constructor|" + "is the implicit copy constructor|" + "is the implicit copy assignment operator}0%1">; + +def note_ovl_candidate_bad_deduction : Note< + "candidate template ignored: failed template argument deduction">; +def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " + "couldn't infer template argument %0">; +def note_ovl_candidate_inconsistent_deduction : Note< + "candidate template ignored: deduced conflicting %select{types|values|" + "templates}0 for parameter %1 (%2 vs. %3)">; +def note_ovl_candidate_explicit_arg_mismatch_named : Note< + "candidate template ignored: invalid explicitly-specified argument " + "for template parameter %0">; +def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< + "candidate template ignored: invalid explicitly-specified argument " + "for %ordinal0 template parameter">; +def note_ovl_candidate_instantiation_depth : Note< + "candidate template ignored: substitution exceeded maximum template " + "instantiation depth">; +def note_ovl_candidate_substitution_failure : Note< + "candidate template ignored: substitution failure %0">; + +// Note that we don't treat templates differently for this diagnostic. +def note_ovl_candidate_arity : Note<"candidate " + "%select{function|function|constructor|function|function|constructor|" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0 %select{|template }1" + "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 " + "%plural{1:was|:were}4 provided">; + +def note_ovl_candidate_deleted : Note< + "candidate %select{function|function|constructor|" + "function |function |constructor |||}0%1 " + "has been explicitly %select{made unavailable|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 +// argument(s) are of the given object type and 2) the fix is usually +// to complete the type, which doesn't involve changes to the call line +// anyway. If people complain, we can change it. +def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1 " + "not viable: cannot convert argument of incomplete type %2 to %3">; +def note_ovl_candidate_bad_overload : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1" + " not viable: no overload of %3 matching %2 for %ordinal4 argument">; +def note_ovl_candidate_bad_conv : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1" + " not viable: no known conversion from %2 to %3 for " + "%select{%ordinal5 argument|object argument}4">; +def note_ovl_candidate_bad_addrspace : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1 not viable: " + "%select{%ordinal6|'this'}5 argument (%2) is in " + "address space %3, but parameter must be in address space %4">; +def note_ovl_candidate_bad_cvr_this : Note<"candidate " + "%select{|function|||function||||" + "function (the implicit copy assignment operator)}0 not viable: " + "'this' argument has type %2, but method is not marked " + "%select{const|volatile|const or volatile|restrict|const or restrict|" + "volatile or restrict|const, volatile, or restrict}3">; +def note_ovl_candidate_bad_cvr : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)}0%1 not viable: " + "%ordinal4 argument (%2) would lose " + "%select{const|volatile|const and volatile|restrict|const and restrict|" + "volatile and restrict|const, volatile, and restrict}3 qualifier" + "%select{||s||s|s|s}3">; +def note_ambiguous_type_conversion: Note< + "because of ambiguity in conversion of %0 to %1">; +def note_ovl_builtin_binary_candidate : Note< + "built-in candidate %0">; +def note_ovl_builtin_unary_candidate : Note< + "built-in candidate %0">; +def err_ovl_no_viable_function_in_init : Error< + "no matching constructor for initialization of %0">; +def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; +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_ambiguous_oper : Error< + "use of overloaded operator '%0' is ambiguous">; +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'">; +def err_ovl_no_viable_subscript : + Error<"no viable overloaded operator[] for type %0">; +def err_ovl_no_oper : + Error<"type %0 does not provide a %select{subscript|call}1 operator">; + +def err_ovl_no_viable_object_call : Error< + "no matching function for call to object of type %0">; +def err_ovl_ambiguous_object_call : Error< + "call to object of type %0 is ambiguous">; +def err_ovl_deleted_object_call : Error< + "call to %select{unavailable|deleted}0 function call operator in type %1">; +def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; +def err_member_call_without_object : Error< + "call to non-static member function without an object argument">; + +// C++ Address of Overloaded Function +def err_addr_ovl_no_viable : Error< + "address of overloaded function %0 does not match required type %1">; +def err_addr_ovl_ambiguous : Error< + "address of overloaded function %0 is ambiguous">; +def err_addr_ovl_not_func_ptrref : Error< + "address of overloaded function %0 cannot be converted to type %1">; + +// C++ Template Declarations +def err_template_param_shadow : Error< + "declaration of %0 shadows template parameter">; +def note_template_param_here : Note<"template parameter is declared here">; +def warn_template_export_unsupported : Warning< + "exported templates are unsupported">; +def err_template_outside_namespace_or_class_scope : Error< + "templates can only be declared in namespace or class scope">; +def err_template_linkage : Error<"templates must have C++ linkage">; +def err_template_typedef : Error<"a typedef cannot be a template">; +def err_template_unnamed_class : Error< + "cannot declare a class template with no name">; +def err_template_param_list_different_arity : Error< + "%select{too few|too many}0 template parameters in template " + "%select{|template parameter }1redeclaration">; +def note_template_param_list_different_arity : Note< + "%select{too few|too many}0 template parameters in template template " + "argument">; +def note_template_prev_declaration : Note< + "previous template %select{declaration|template parameter}0 is here">; +def err_template_param_different_kind : Error< + "template parameter has a different kind in template " + "%select{|template parameter }0redeclaration">; +def note_template_param_different_kind : Note< + "template parameter has a different kind in template argument">; +def err_template_nontype_parm_different_type : Error< + "template non-type parameter has a different type %0 in template " + "%select{|template parameter }1redeclaration">; + +def note_template_nontype_parm_different_type : Note< + "template non-type parameter has a different type %0 in template argument">; +def note_template_nontype_parm_prev_declaration : Note< + "previous non-type template parameter with type %0 is here">; +def err_template_nontype_parm_bad_type : Error< + "a non-type template parameter cannot have type %0">; +def err_template_param_default_arg_redefinition : Error< + "template parameter redefines default argument">; +def note_template_param_prev_default_arg : Note< + "previous default template argument defined here">; +def err_template_param_default_arg_missing : Error< + "template parameter missing a default argument">; +def err_template_parameter_default_in_function_template : Error< + "a template parameter of a function template cannot have a default argument " + "in C++98">; +def err_template_parameter_default_template_member : Error< + "cannot add a default template argument to the definition of a member of a " + "class template">; +def err_template_parameter_default_friend_template : Error< + "default template argument not permitted on a friend template">; + +def err_template_variable : Error<"variable %0 declared as a template">; +def err_template_variable_noparams : Error< + "extraneous 'template<>' in declaration of variable %0">; +def err_template_tag_noparams : Error< + "extraneous 'template<>' in declaration of %0 %1">; +def err_template_decl_ref : Error< + "cannot refer to class template %0 without a template argument list">; + +// C++ Template Argument Lists +def err_template_missing_args : Error< + "use of class template %0 requires template arguments">; +def err_template_arg_list_different_arity : Error< + "%select{too few|too many}0 template arguments for " + "%select{class template|function template|template template parameter" + "|template}1 %2">; +def note_template_decl_here : Note<"template is declared here">; +def note_member_of_template_here : Note<"member is declared here">; +def err_template_arg_must_be_type : Error< + "template argument for template type parameter must be a type">; +def err_template_arg_must_be_expr : Error< + "template argument for non-type template parameter must be an expression">; +def err_template_arg_nontype_ambig : Error< + "template argument for non-type template parameter is treated as type %0">; +def err_template_arg_must_be_template : Error< + "template argument for template template parameter must be a class template">; +def err_template_arg_local_type : Error<"template argument uses local type %0">; +def err_template_arg_unnamed_type : Error< + "template argument uses unnamed type">; +def note_template_unnamed_type_here : Note< + "unnamed type used in template argument was declared here">; +def err_template_arg_overload_type : Error< + "template argument is the type of an unresolved overloaded function">; +def err_template_arg_not_class_template : Error< + "template argument does not refer to a class template or template " + "template parameter">; +def note_template_arg_refers_here_func : Note< + "template argument refers to function template %0, here">; +def err_template_arg_template_params_mismatch : Error< + "template template argument has different template parameters than its " + "corresponding template template parameter">; +def err_template_arg_not_integral_or_enumeral : Error< + "non-type template argument of type %0 must have an integral or enumeration" + " type">; +def err_template_arg_not_ice : Error< + "non-type template argument of type %0 is not an integral constant " + "expression">; +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)">; +def err_template_arg_not_convertible : Error< + "non-type template argument of type %0 cannot be converted to a value " + "of type %1">; +def warn_template_arg_negative : Warning< + "non-type template argument with value '%0' converted to '%1' for unsigned " + "template parameter of type %2">; +def warn_template_arg_too_large : Warning< + "non-type template argument value '%0' truncated to '%1' for " + "template parameter of type %2">; +def err_template_arg_no_ref_bind : Error< + "non-type template parameter of reference type %0 cannot bind to template " + "argument of type %1">; +def err_template_arg_ref_bind_ignores_quals : Error< + "reference binding of non-type template parameter of type %0 to template " + "argument of type %1 ignores qualifiers">; +def err_template_arg_not_decl_ref : Error< + "non-type template argument does not refer to any declaration">; +def err_template_arg_not_object_or_func_form : Error< + "non-type template argument does not directly refer to an object or " + "function">; +def err_template_arg_not_address_of : Error< + "non-type template argument for template parameter of pointer type %0 must " + "have its address taken">; +def err_template_arg_address_of_non_pointer : Error< + "address taken in non-type template argument for template parameter of " + "reference type %0">; +def err_template_arg_reference_var : Error< + "non-type template argument of reference type %0 is not an object">; +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 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">; +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 err_template_arg_extra_parens : Error< + "non-type template argument cannot be surrounded by parentheses">; +def err_pointer_to_member_type : Error< + "invalid use of pointer to member type after %select{.*|->*}0">; + +// 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 " + "class template">; +def note_specialized_entity : Note< + "explicitly specialized declaration is here">; +def err_template_spec_decl_function_scope : Error< + "explicit specialization of %0 in function scope">; +def err_template_spec_decl_class_scope : Error< + "explicit specialization of %0 in class scope">; +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 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">; +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">; +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">; +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">; +def err_specialization_after_instantiation : Error< + "explicit specialization of %0 after instantiation">; +def note_instantiation_required_here : Note< + "%select{implicit|explicit}0 instantiation first required here">; +def err_template_spec_friend : Error< + "template specialization declaration cannot be a friend">; +def err_template_spec_default_arg : Error< + "default argument not permitted on an explicit " + "%select{instantiation|specialization}0 of function %1">; +def err_not_class_template_specialization : Error< + "cannot specialize a %select{dependent template|template template " + "parameter}0">; + +// C++ class template specializations and out-of-line definitions +def err_template_spec_needs_header : Error< + "template specialization requires 'template<>'">; +def err_template_spec_needs_template_parameters : Error< + "template specialization or definition requires a template parameter list " + "corresponding to the nested type %0">; +def err_template_param_list_matches_nontemplate : Error< + "template parameter list matching the non-templated nested type %0 should " + "be empty ('template<>')">; +def err_template_spec_extra_headers : Error< + "extraneous template parameter list in template specialization or " + "out-of-line template definition">; +def warn_template_spec_extra_headers : Warning< + "extraneous template parameter list in template specialization">; +def note_explicit_template_spec_does_not_need_header : Note< + "'template<>' header not required for explicitly-specialized class %0 " + "declared here">; +def err_template_qualified_declarator_no_match : Error< + "nested name specifier '%0' for declaration does not refer into a class, " + "class template or class template partial specialization">; + +// C++ Class Template Partial Specialization +def err_default_arg_in_partial_spec : Error< + "default template argument in a class template partial specialization">; +def err_dependent_non_type_arg_in_partial_spec : Error< + "non-type template argument depends on a template parameter of the " + "partial specialization">; +def err_dependent_typed_non_type_arg_in_partial_spec : Error< + "non-type template argument specializes a template parameter with " + "dependent type %0">; +def err_partial_spec_args_match_primary_template : Error< + "class template partial specialization does not specialize any template " + "argument; to %select{declare|define}0 the primary template, remove the " + "template argument list">; +def warn_partial_specs_not_deducible : Warning< + "class template partial specialization contains " + "%select{a template parameter|template parameters}0 that can not be " + "deduced; this partial specialization will never be used">; +def note_partial_spec_unused_parameter : Note< + "non-deducible template parameter %0">; +def err_partial_spec_ordering_ambiguous : Error< + "ambiguous partial specializations of %0">; +def note_partial_spec_match : Note<"partial specialization matches %0">; +def err_partial_spec_redeclared : Error< + "class template partial specialization %0 cannot be redeclared">; +def note_prev_partial_spec_here : Note< + "previous declaration of class template partial specialization %0 is here">; +def err_partial_spec_fully_specialized : Error< + "partial specialization of %0 does not use any of its template parameters">; + +// C++ Function template specializations +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 " + "arguments to identify a particular function template">; +def note_function_template_spec_matched : Note< + "function template matches specialization %0">; + +// C++ Template Instantiation +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">; + +def err_template_instantiate_undefined : Error< + "%select{implicit|explicit}0 instantiation of undefined template %1">; +def err_implicit_instantiate_member_undefined : Error< + "implicit instantiation of undefined member %0">; +def note_template_class_instantiation_here : Note< + "in instantiation of template class %0 requested here">; +def note_template_member_class_here : Note< + "in instantiation of member class %0 requested here">; +def note_template_member_function_here : Note< + "in instantiation of member function %q0 requested here">; +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_default_arg_instantiation_here : Note< + "in instantiation of default argument for '%0' required here">; +def note_default_function_arg_instantiation_here : Note< + "in instantiation of default function argument expression " + "for '%0' required here">; +def note_explicit_template_arg_substitution_here : Note< + "while substituting explicitly-specified template arguments into function " + "template %0 %1">; +def note_function_template_deduction_instantiation_here : Note< + "while substituting deduced template arguments into function template %0 " + "%1">; +def note_partial_spec_deduct_instantiation_here : Note< + "during template argument deduction for class template partial " + "specialization %0 %1">; +def note_prior_template_arg_substitution : Note< + "while substituting prior template arguments into %select{non-type|template}0" + " template parameter%1 %2">; +def note_template_default_arg_checking : Note< + "while checking a default template argument used here">; +def note_instantiation_contexts_suppressed : Note< + "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to " + "see all)">; + +def err_field_instantiates_to_function : Error< + "data member instantiated with function type %0">; +def err_nested_name_spec_non_tag : Error< + "type %0 cannot be used prior to '::' because it has no members">; + +// C++ Explicit Instantiation +def err_explicit_instantiation_duplicate : Error< + "duplicate explicit instantiation of %0">; +def note_previous_explicit_instantiation : Note< + "previous explicit instantiation is here">; +def ext_explicit_instantiation_after_specialization : Extension< + "explicit instantiation of %0 that occurs after an explicit " + "specialization will be ignored (C++0x extension)">; +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< + "non-templated declaration is here">; +def err_explicit_instantiation_out_of_scope : Error< + "explicit instantiation of %0 not in a namespace enclosing %1">; +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<DiagGroup<"-Wc++0x-compat"> >; +def warn_explicit_instantiation_must_be_global_0x : Warning< + "explicit instantiation of %0 must occur at global scope">, + InGroup<DiagGroup<"-Wc++0x-compat"> >; + +def err_explicit_instantiation_requires_name : Error< + "explicit instantiation declaration requires a name">; +def err_explicit_instantiation_of_typedef : Error< + "explicit instantiation of typedef %0">; +def err_explicit_instantiation_not_known : Error< + "explicit instantiation of %0 does not refer to a function template, member " + "function, member class, or static data member">; +def note_explicit_instantiation_here : Note< + "explicit instantiation refers here">; +def err_explicit_instantiation_data_member_not_instantiated : Error< + "explicit instantiation refers to static data member %q0 that is not an " + "instantiation">; +def err_explicit_instantiation_member_function_not_instantiated : Error< + "explicit instantiation refers to member function %q0 that is not an " + "instantiation">; +def err_explicit_instantiation_ambiguous : Error< + "partial ordering for explicit instantiation of %0 is ambiguous">; +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 err_explicit_instantiation_without_qualified_id : Error< + "qualifier in explicit instantiation of %q0 requires a template-id">; +def err_explicit_instantiation_without_qualified_id_quals : Error< + "qualifier in explicit instantiation of '%0%1' requires a template-id">; +def err_explicit_instantiation_unqualified_wrong_namespace : Error< + "explicit instantiation of %q0 must occur in %1">; +def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning< + "explicit instantiation of %q0 must occur in %1">, + InGroup<DiagGroup<"c++0x-compat"> >; +def err_explicit_instantiation_undefined_member : Error< + "explicit instantiation of undefined %select{member class|member function|" + "static data member}0 %1 of class template %2">; +def err_explicit_instantiation_undefined_func_template : Error< + "explicit instantiation of undefined function template %0">; +def err_explicit_instantiation_declaration_after_definition : Error< + "explicit instantiation declaration (with 'extern') follows explicit " + "instantiation definition (without 'extern')">; +def note_explicit_instantiation_definition_here : Note< + "explicit instantiation definition is here">; + +// C++ typename-specifiers +def err_typename_nested_not_found : Error<"no type named %0 in %1">; +def err_typename_nested_not_type : Error< + "typename specifier refers to non-type member %0 in %1">; +def note_typename_refers_here : Note< + "referenced member %0 is declared here">; +def err_typename_missing : Error< + "missing 'typename' prior to dependent type name '%0%1'">; + +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< + "class template declared here">; +def err_template_kw_missing : Error< + "missing 'template' keyword prior to dependent template name '%0%1'">; + +// C++0x Variadic Templates +def err_template_param_pack_default_arg : Error< + "template parameter pack cannot have a default argument">; +def err_template_param_pack_must_be_last_template_parameter : Error< + "template parameter pack must be the last template parameter">; + +def err_unexpected_typedef : Error< + "unexpected type name %0: expected expression">; +def err_unexpected_namespace : Error< + "unexpected namespace name %0: expected expression">; +def err_undeclared_var_use : Error<"use of undeclared identifier %0">; +def note_dependent_var_use : Note<"must qualify identifier to find this " + "declaration in dependent base class">; +def err_undeclared_use : Error<"use of undeclared %0">; +def warn_deprecated : Warning<"%0 is deprecated">, + InGroup<DiagGroup<"deprecated-declarations">>; +def warn_unavailable : Warning<"%0 is unavailable">, + InGroup<DiagGroup<"unavailable-declarations">>; +def note_unavailable_here : Note< + "function has been explicitly marked %select{unavailable|deleted}0 here">; +def warn_not_enough_argument : Warning< + "not enough variable arguments in %0 declaration to fit a sentinel">; +def warn_missing_sentinel : Warning < + "missing sentinel in %select{function call|method dispatch|block call}0">; +def note_sentinel_here : Note< + "%select{function|method|block}0 has been explicitly marked sentinel here">; +def warn_missing_prototype : Warning< + "no previous prototype for function %0">, + InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore; +def err_redefinition : Error<"redefinition of %0">; +def err_definition_of_implicitly_declared_member : Error< + "definition of implicitly declared %select{constructor|copy constructor|" + "copy assignment operator|destructor}1">; + +def warn_redefinition_of_typedef : Warning< + "redefinition of typedef %0 is invalid in C">, + InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; + +def err_static_non_static : Error< + "static declaration of %0 follows non-static declaration">; +def err_non_static_static : Error< + "non-static declaration of %0 follows static declaration">; +def err_non_thread_thread : Error< + "non-thread-local declaration of %0 follows thread-local declaration">; +def err_thread_non_thread : Error< + "thread-local declaration of %0 follows non-thread-local declaration">; +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 err_redefinition_different_typedef : Error< + "typedef redefinition with different types (%0 vs %1)">; +def err_tag_reference_non_tag : Error< + "elaborated type refers to %select{a non-tag type|a typedef|a template}0">; +def err_tag_reference_conflict : Error< + "implicit declaration introduced by elaborated type conflicts with " + "%select{a declaration|a typedef|a template}0 of the same name">; +def err_dependent_tag_decl : Error< + "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " + "in a dependent scope">; +def err_tag_definition_of_typedef : Error< + "definition of type %0 conflicts with typedef of the same name">; +def err_conflicting_types : Error<"conflicting types for %0">; +def err_nested_redefinition : Error<"nested redefinition of %0">; +def err_use_with_wrong_tag : Error< + "use of %0 with tag type that does not match previous declaration">; +def warn_struct_class_tag_mismatch : Warning< + "%select{struct|class}0 %select{|template}1 %2 was previously declared " + "as a %select{class|struct}0 %select{|template}1">, + InGroup<MismatchedTags>, DefaultIgnore; +def ext_forward_ref_enum : Extension< + "ISO C forbids forward references to 'enum' types">; +def err_forward_ref_enum : Error< + "ISO C++ forbids forward references to 'enum' types">; +def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; +def err_duplicate_member : Error<"duplicate member %0">; +def err_misplaced_ivar : Error< + "ivars may not be placed in %select{categories|class extension}0">; +def ext_enum_value_not_int : Extension< + "ISO C restricts enumerator values to range of 'int' (%0 is too " + "%select{small|large}1)">; +def warn_enum_too_large : Warning< + "enumeration values exceed range of largest integer">; +def warn_enumerator_too_large : Warning< + "enumerator value %0 is not representable in the largest integer type">; + +def warn_illegal_constant_array_size : Extension< + "size of static array must be an integer constant expression">; +def err_vm_decl_in_file_scope : Error< + "variably modified type declaration not allowed at file scope">; +def err_vm_decl_has_extern_linkage : Error< + "variably modified type declaration can not have 'extern' linkage">; +def err_typecheck_field_variable_size : Error< + "fields must have a constant size: 'variable length array in structure' " + "extension will never be supported">; +def err_vm_func_decl : Error< + "function declaration cannot have variably modified type">; + +def err_typecheck_negative_array_size : Error<"array size is negative">; +def warn_typecheck_function_qualifiers : Warning< + "qualifier on function type %0 has unspecified behavior">; +def err_typecheck_invalid_restrict_not_pointer : Error< + "restrict requires a pointer or reference (%0 is invalid)">; +def err_typecheck_invalid_restrict_not_pointer_noarg : Error< + "restrict requires a pointer or reference">; +def err_typecheck_invalid_restrict_invalid_pointee : Error< + "pointer to function type %0 may not be 'restrict' qualified">; +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 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">; +def err_block_extern_cant_init : Error< + "'extern' variable cannot have an initializer">; +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< + "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; +def err_excess_initializers_in_char_array_initializer : Error< + "excess elements in char array initializer">; +def warn_excess_initializers_in_char_array_initializer : ExtWarn< + "excess elements in char array initializer">; +def warn_initializer_string_for_char_array_too_long : ExtWarn< + "initializer-string for char array is too long">; +def warn_missing_field_initializers : Warning< + "missing field '%0' initializer">, + InGroup<MissingFieldInitializers>, DefaultIgnore; +def warn_braces_around_scalar_init : Warning< + "braces around scalar initializer">; +def err_many_braces_around_scalar_init : Error< + "too many braces around scalar initializer">; +def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; +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_objc_class : Error< + "cannot initialize Objective-C class type %0">; +def err_implicit_empty_initializer : Error< + "initializer for aggregate with no elements requires explicit braces">; +def err_bitfield_has_negative_width : Error< + "bit-field %0 has negative width (%1)">; +def err_anon_bitfield_has_negative_width : Error< + "anonymous bit-field has negative width (%0)">; +def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">; +def err_bitfield_width_exceeds_type_size : Error< + "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">; +def err_anon_bitfield_width_exceeds_type_size : Error< + "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">; + +// 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 " + "truncated to %2 bits">; +def warn_anon_bitfield_width_exceeds_type_size : Warning< + "size of anonymous bit-field (%0 bits) exceeds size of its type; value will " + "be truncated to %1 bits">; + +def warn_missing_braces : Warning< + "suggest braces around initialization of subobject">, + InGroup<DiagGroup<"missing-braces">>, DefaultIgnore; + +def err_redefinition_of_label : Error<"redefinition of label '%0'">; +def err_undeclared_label_use : Error<"use of undeclared label '%0'">; + +def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; +def err_switch_into_protected_scope : Error< + "illegal switch case into protected scope">; +def err_indirect_goto_without_addrlabel : Error< + "indirect goto in function with no address-of-label expressions">; +def warn_indirect_goto_in_protected_scope : Warning< + "indirect goto might cross protected scopes">, + InGroup<DiagGroup<"label-address-scope">>; +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_cleanup : Note< + "jump bypasses initialization of variable with __attribute__((cleanup))">; +def note_protected_by_vla_typedef : Note< + "jump bypasses initialization of VLA typedef">; +def note_protected_by_vla : Note< + "jump bypasses initialization of variable length array">; +def note_protected_by_objc_try : Note< + "jump bypasses initialization of @try block">; +def note_protected_by_objc_catch : Note< + "jump bypasses initialization of @catch block">; +def note_protected_by_objc_finally : Note< + "jump bypasses initialization of @finally block">; +def note_protected_by_objc_synchronized : Note< + "jump bypasses initialization of @synchronized block">; +def note_protected_by_cxx_try : Note< + "jump bypasses initialization of try block">; +def note_protected_by_cxx_catch : Note< + "jump bypasses initialization of catch block">; +def note_protected_by___block : Note< + "jump bypasses setup of __block variable">; + +def note_exits_cleanup : Note< + "jump exits scope of variable with __attribute__((cleanup))">; +def note_exits_dtor : Note< + "jump exits scope of variable with non-trivial destructor">; +def note_exits___block : Note< + "jump exits scope of __block variable">; +def note_exits_objc_try : Note< + "jump exits @try block">; +def note_exits_objc_catch : Note< + "jump exits @catch block">; +def note_exits_objc_finally : Note< + "jump exits @finally block">; +def note_exits_objc_synchronized : Note< + "jump exits @synchronized block">; +def note_exits_cxx_try : Note< + "jump exits try block">; +def note_exits_cxx_catch : Note< + "jump exits catch block">; + +def err_func_returning_array_function : Error< + "function cannot return %select{array|function}0 type %1">; +def err_field_declared_as_function : Error<"field %0 declared as a function">; +def err_field_incomplete : Error<"field has incomplete type %0">; +def ext_variable_sized_type_in_struct : ExtWarn< + "field %0 with variable sized type %1 not at the end of a struct or class is" + " a GNU extension">, InGroup<GNU>; + +def err_flexible_array_empty_struct : Error< + "flexible array %0 not allowed in otherwise empty struct">; +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">; +def ext_flexible_array_in_array : Extension< + "%0 may not be used as an array element due to flexible array member">; +def err_flexible_array_init_nonempty : Error< + "non-empty initialization of flexible array member inside subobject">; +def err_flexible_array_init_needs_braces : Error< + "flexible array requires brace-enclosed initializer">; +def err_illegal_decl_array_of_functions : Error< + "'%0' declared as array of functions of type %1">; +def err_illegal_decl_array_incomplete_type : Error< + "array has incomplete element type %0">; +def err_illegal_decl_array_of_references : Error< + "'%0' declared as array of references of type %1">; +def err_array_star_outside_prototype : Error< + "star modifier used outside of function prototype">; +def err_illegal_decl_pointer_to_reference : Error< + "'%0' declared as a pointer to a reference of type %1">; +def err_illegal_decl_mempointer_to_reference : Error< + "'%0' declared as a member pointer to a reference of type %1">; +def err_illegal_decl_mempointer_to_void : Error< + "'%0' declared as a member pointer to void">; +def err_illegal_decl_mempointer_in_nonclass : Error< + "'%0' does not point into a class">; +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">; + +// 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}0' to an overloaded " + "function">; +def ext_sizeof_void_type : Extension< + "invalid application of '%0' to a void type">, InGroup<PointerArith>; +def err_sizeof_alignof_incomplete_type : Error< + "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">; +def err_sizeof_alignof_bitfield : Error< + "invalid application of '%select{sizeof|__alignof}0' to bit-field">; +def err_offsetof_incomplete_type : Error< + "offsetof of incomplete type %0">; +def err_offsetof_record_type : Error< + "offsetof requires struct, union, or class type, %0 invalid">; +def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; +def ext_offsetof_extended_field_designator : Extension< + "using extended field designator is an extension">; +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">; + +def warn_floatingpoint_eq : Warning< + "comparing floating point with == or != is unsafe">, + InGroup<DiagGroup<"float-equal">>, DefaultIgnore; + +def warn_division_by_zero : Warning<"division by zero is undefined">; +def warn_remainder_by_zero : Warning<"remainder by zero is undefined">; +def warn_shift_negative : Warning<"shift count is negative">; +def warn_shift_gt_typewidth : Warning<"shift count >= width of type">; + +def warn_precedence_bitwise_rel : Warning< + "%0 has lower precedence than %1; %1 will be evaluated first">, + InGroup<Parentheses>; +def note_precedence_bitwise_first : Note< + "place parentheses around the %0 expression to evaluate it first">; +def note_precedence_bitwise_silence : Note< + "place parentheses around the %0 expression to silence this warning">; + +def err_sizeof_nonfragile_interface : Error< + "invalid application of '%select{alignof|sizeof}1' to interface %0 in " + "non-fragile ABI">; +def err_atdef_nonfragile_interface : Error< + "invalid application of @defs in non-fragile ABI">; +def err_subscript_nonfragile_interface : Error< + "subscript requires size of interface %0, which is not constant in " + "non-fragile ABI">; + +def err_arithmetic_nonfragile_interface : Error< + "arithmetic on pointer to interface %0, which is not a constant size in " + "non-fragile ABI">; + + +def ext_subscript_non_lvalue : Extension< + "ISO C90 does not allow subscripting non-lvalue array">; +def err_typecheck_subscript_value : Error< + "subscripted value is not an array, pointer, or vector">; +def err_typecheck_subscript_not_integer : Error< + "array subscript is not an integer">; +def err_subscript_function_type : Error< + "subscript of pointer to function type %0">; +def err_subscript_incomplete_type : Error< + "subscript of pointer to incomplete type %0">; +def err_typecheck_member_reference_struct_union : Error< + "member reference base type %0 is not a structure or union">; +def err_typecheck_member_reference_ivar : Error< + "%0 does not have a member named %1">; +def err_typecheck_member_reference_arrow : Error< + "member reference type %0 is not a pointer">; +def err_typecheck_member_reference_suggestion : Error< + "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">; +def err_typecheck_member_reference_type : Error< + "cannot refer to type member %0 in %1 with '%select{.|->}2'">; +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 has function type %0; perhaps you meant to call " + "this function with '()'?">; +def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, + InGroup<CharSubscript>, DefaultIgnore; + +def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; +def err_no_member : Error<"no member named %0 in %1">; + +def err_member_redeclared : Error<"class member cannot be redeclared">; +def err_member_def_undefined_record : Error< + "out-of-line definition of %0 from class %1 without definition">; +def err_member_def_does_not_match : Error< + "out-of-line definition of %0 does not match any declaration in %1">; +def err_nonstatic_member_out_of_line : Error< + "non-static data member defined out-of-line">; +def err_qualified_typedef_declarator : Error< + "typedef declarator cannot be qualified">; +def err_qualified_param_declarator : Error< + "parameter declarator cannot be qualified">; +def err_out_of_line_declaration : Error< + "out-of-line declaration of a member must be a definition">; +def note_member_def_close_match : Note<"member declaration nearly matches">; +def err_typecheck_ivar_variable_size : Error< + "instance variables must have a constant size">; +def err_ivar_reference_type : Error< + "instance variables cannot be of reference type">; +def err_typecheck_illegal_increment_decrement : Error< + "cannot %select{decrement|increment}1 value of type %0">; +def err_typecheck_arithmetic_incomplete_type : Error< + "arithmetic on pointer to incomplete type %0">; +def err_typecheck_pointer_arith_function_type : Error< + "arithmetic on pointer to function type %0">; +def err_typecheck_pointer_arith_void_type : Error< + "arithmetic on pointer to void type">; +def err_typecheck_decl_incomplete_type : Error< + "variable has incomplete type %0">; +def ext_typecheck_decl_incomplete_type : ExtWarn< + "tentative definition of variable with internal linkage has incomplete non-array type %0">; +def err_tentative_def_incomplete_type : Error< + "tentative definition has type %0 that is never completed">; +def err_tentative_def_incomplete_type_arr : Error< + "tentative definition has array of type %0 that is never completed">; +def warn_tentative_incomplete_array : Warning< + "tentative array definition assumed to have one element">; +def err_typecheck_incomplete_array_needs_initializer : Error< + "definition of variable with array type needs an explicit size " + "or an initializer">; +def err_array_init_not_init_list : Error< + "array initializer must be an initializer " + "list%select{| or string literal}0">; +def warn_deprecated_string_literal_conversion : Warning< + "conversion from string literal to %0 is deprecated">, InGroup<Deprecated>; +def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; +def err_typecheck_sclass_fscope : Error< + "illegal storage class on file-scoped variable">; +def err_unsupported_global_register : Error< + "global register variables are not supported">; +def err_typecheck_sclass_func : Error<"illegal storage class on function">; +def err_static_block_func : Error< + "function declared in block scope cannot have 'static' storage class">; +def err_typecheck_address_of : Error<"address of %0 requested">; +def ext_typecheck_addrof_void : Extension< + "ISO C forbids taking the address of an expression of type 'void'">; +def err_unqualified_pointer_member_function : Error< + "must explicitly qualify member function %0 when taking its address">; +def err_typecheck_invalid_lvalue_addrof : Error< + "address expression must be an lvalue or a function designator">; +def ext_typecheck_addrof_class_temporary : ExtWarn< + "taking the address of a temporary object of type %0">, + InGroup<DiagGroup<"address-of-temporary">>, DefaultError; +def err_typecheck_addrof_class_temporary : Error< + "taking the address of a temporary object of type %0">; +def err_typecheck_unary_expr : Error< + "invalid argument type %0 to unary expression">; +def err_typecheck_indirection_requires_pointer : Error< + "indirection requires pointer operand (%0 invalid)">; +def err_indirection_requires_nonfragile_object : Error< + "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">; +def err_direct_interface_unsupported : Error< + "indirection to an interface is not supported (%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< + "ordered comparison between pointer and integer (%0 and %1)">; +def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension< + "ordered comparison between pointer and zero (%0 and %1) is an extension">; +def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< + "ordered comparison of function pointers (%0 and %1)">; +def ext_typecheck_comparison_of_fptr_to_void : Extension< + "equality comparison between function pointer and void pointer (%0 and %1)">; +def ext_typecheck_comparison_of_pointer_integer : ExtWarn< + "comparison between pointer and integer (%0 and %1)">; +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_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">; +def warn_mixed_sign_comparison : Warning< + "comparison of integers of different signs: %0 and %1">, + InGroup<SignCompare>, DefaultIgnore; +def warn_mixed_sign_conditional : Warning< + "operands of ? are integers of different signs: %0 and %1">, + InGroup<SignCompare>, DefaultIgnore; +def warn_lunsigned_always_true_comparison : Warning< + "comparison of unsigned expression %0 is always %1">, + InGroup<SignCompare>, DefaultIgnore; +def warn_runsigned_always_true_comparison : Warning< + "comparison of %0 unsigned expression is always %1">, + InGroup<SignCompare>, DefaultIgnore; + +def err_invalid_this_use : Error< + "invalid use of 'this' outside of a nonstatic 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_qualified_typedef_function_type_use : Error< + "a qualified function type cannot be used to declare a nonmember function " + "or a static member function">; + +def err_invalid_non_static_member_use : Error< + "invalid use of nonstatic data member %0">; +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_printf_nonliteral_noargs : Warning< + "format string is not a string literal (potentially insecure)">, + InGroup<FormatSecurity>; +def warn_printf_nonliteral : Warning< + "format string is not a string literal">, + InGroup<FormatNonLiteral>, DefaultIgnore; + +def err_unexpected_interface : Error< + "unexpected interface name %0: expected expression">; +def err_ref_non_value : Error<"%0 does not refer to a value">; +def err_ref_vm_type : Error< + "cannot refer to declaration with a variably modified type inside block">; +def err_ref_array_type : Error< + "cannot refer to declaration with an array type inside block">; +def err_property_not_found : Error< + "property %0 not found on object of type %1">; +def err_duplicate_property : Error< + "property has a previous declaration">; +def ext_gnu_void_ptr : Extension< + "use of GNU void* extension">, InGroup<PointerArith>; +def ext_gnu_ptr_func_arith : Extension< + "arithmetic on pointer to function type %0 is a GNU extension">, + InGroup<PointerArith>; +def error_readonly_property_assignment : Error< + "assigning to property with 'readonly' attribute 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 error_no_subobject_property_setting : Error< + "expression is not assignable using property assignment syntax">; + +def ext_freestanding_complex : Extension< + "complex numbers are an extension in a freestanding C99 implementation">; + + +// Obj-c expressions +def warn_root_inst_method_not_found : Warning< + "instance method %0 is being used on 'Class' which is not in the root class">; +def warn_class_method_not_found : Warning< + "method %objcclass0 not found (return type defaults to 'id')">; +def warn_inst_method_not_found : Warning< + "method %objcinstance0 not found (return type defaults to 'id')">; +def error_no_super_class_message : Error< + "no @interface declaration found in class messaging of %0">; +def error_no_super_class : Error< + "no super class declared in @interface for %0">; +def err_invalid_receiver_to_message : Error< + "invalid receiver to message expression">; +def err_invalid_receiver_to_message_super : Error< + "'super' is only valid in a method body">; +def err_invalid_receiver_class_message : Error< + "receiver type %0 is not an Objective-C class">; +def warn_bad_receiver_type : Warning< + "receiver type %0 is not 'id' or interface pointer, consider " + "casting it to 'id'">; +def err_bad_receiver_type : Error<"bad receiver type %0">; +def err_unknown_receiver_suggest : Error< + "unknown receiver %0; did you mean %1?">; +def error_objc_throw_expects_object : Error< + "@throw requires an Objective-C object type (%0 invalid)">; +def error_objc_synchronized_expects_object : Error< + "@synchronized requires an Objective-C object type (%0 invalid)">; +def error_rethrow_used_outside_catch : Error< + "@throw (rethrow) used outside of a @catch block">; +def err_attribute_multiple_objc_gc : Error< + "multiple garbage collection attributes specified for type">; +def err_catch_param_not_objc_type : Error< + "@catch parameter is not a pointer to an interface type">; +def err_illegal_qualifiers_on_catch_parm : Error< + "illegal qualifiers on @catch parameter">; +def err_storage_spec_on_catch_parm : Error< + "@catch parameter cannot have storage specifier %select{|'typedef'|'extern'|" + "'static'|'auto'|'register'|'__private_extern__'|'mutable'}0">; +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 warn_setter_getter_impl_required : Warning< + "property %0 requires method %1 to be defined - " + "use @synthesize, @dynamic or provide a method implementation">; +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 category">; +def note_property_impl_required : Note< + "implementation is here">; +def note_parameter_named_here : Note< + "passing argument to parameter %0 here">; +def note_parameter_here : Note< + "passing argument to parameter here">; + +// C++ casts +// These messages adhere to the TryCast pattern: %0 is an int specifying the +// cast type, %1 is the source type, %2 is the destination type. +def err_bad_cxx_cast_generic : Error< + "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" + "functional-style cast}0 from %1 to %2 is not allowed">; +def err_bad_cxx_cast_rvalue : Error< + "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" + "functional-style cast}0 from rvalue to reference type %2">; +def err_bad_cxx_cast_const_away : Error< + "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" + "functional-style cast}0 from %1 to %2 casts away constness">; +def err_bad_const_cast_dest : Error< + "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " + "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 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< + "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " + "to scalar %2 of different size">; +def err_bad_cxx_cast_scalar_to_vector_different_size : Error< + "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 " + "to vector %2 of different size">; +def err_bad_cxx_cast_vector_to_vector_different_size : Error< + "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " + "to vector %2 of different size">; +def err_bad_lvalue_to_rvalue_cast : Error< + "cannot cast from lvalue of type %1 to rvalue reference type %2; types are " + "not compatible">; +def err_bad_static_cast_pointer_nonpointer : Error< + "cannot cast from type %1 to pointer type %2">; +def err_bad_static_cast_member_pointer_nonmp : Error< + "cannot cast from type %1 to member pointer type %2">; +def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; + +// These messages don't adhere to the pattern. +// FIXME: Display the path somehow better. +def err_ambiguous_base_to_derived_cast : Error< + "ambiguous cast from base %0 to derived %1:%2">; +def err_static_downcast_via_virtual : Error< + "cannot cast %0 to %1 via virtual base %2">; +def err_downcast_from_inaccessible_base : Error< + "cannot cast %select{private|protected}2 base class %1 to %0">; +def err_upcast_to_inaccessible_base : Error< + "cannot cast %0 to its %select{private|protected}2 base class %1">; +def err_bad_dynamic_cast_not_ref_or_ptr : Error< + "%0 is not a reference or pointer">; +def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">; +def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">; +def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">; +def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">; + +// Other C++ expressions +def err_need_header_before_typeid : Error< + "you need to include <typeinfo> before using the 'typeid' operator">; +def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">; +def err_static_illegal_in_new : Error< + "the 'static' modifier for the array size is not legal in new expressions">; +def err_array_new_needs_size : Error< + "array size must be specified in new expressions">; +def err_bad_new_type : Error< + "cannot allocate %select{function|reference}1 type %0 with new">; +def err_new_incomplete_type : Error< + "allocation of incomplete type %0">; +def err_new_array_nonconst : Error< + "only the first dimension of an allocated array may have dynamic size">; +def err_new_array_init_args : Error< + "array 'new' cannot have initialization arguments">; +def err_new_paren_array_nonconst : Error< + "when type is in parentheses, array cannot have dynamic size">; +def err_placement_new_non_placement_delete : Error< + "'new' expression with placement arguments refers to non-placement " + "'operator delete'">; +def err_array_size_not_integral : Error< + "array size expression must have integral or enumerated type, not %0">; +def err_default_init_const : Error< + "default initialization of an object of const type %0" + "%select{| requires a user-provided default constructor}1">; +def err_delete_operand : Error<"cannot delete expression of type %0">; +def ext_delete_void_ptr_operand : ExtWarn< + "cannot delete expression with pointer-to-'void' type %0">; +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">; +def err_no_suitable_delete_member_function_found : Error< + "no suitable member %0 in %1">; +def note_member_declared_here : Note< + "member %0 declared here">; +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 : Error<"cannot catch incomplete type %0">; +def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">; +def err_qualified_catch_declarator : Error< + "exception declarator cannot be qualified">; +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">; +def warn_exception_caught_by_earlier_handler : Warning< + "exception of type %0 will be caught by earlier handler">; +def note_previous_exception_handler : Note<"for type %0">; + +def err_conditional_void_nonvoid : Error< + "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " + "is of type %0">; +def err_conditional_ambiguous : Error< + "conditional expression is ambiguous; %0 can be converted to %1 " + "and vice versa">; +def err_conditional_ambiguous_ovl : Error< + "conditional expression is ambiguous; %0 and %1 can be converted to several " + "common types">; + +def err_throw_incomplete : Error< + "cannot throw object of incomplete type %0">; +def err_throw_incomplete_ptr : Error< + "cannot throw pointer to object of incomplete type %0">; +def err_return_in_constructor_handler : Error< + "return in the catch of a function try block of a constructor is illegal">; + +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 err_pseudo_dtor_type_mismatch : Error< + "the type of object expression (%0) does not match the type being destroyed " + "(%1) in pseudo-destructor expression">; +def err_pseudo_dtor_call_with_args : Error< + "call to pseudo-destructor cannot have any arguments">; +def err_dtor_expr_without_call : Error< + "%select{destructor reference|pseudo-destructor expression}0 must be " + "called immediately with '()'">; +def err_pseudo_dtor_destructor_non_type : Error< + "%0 does not refer to a type name in pseudo-destructor expression; expected " + "the name of type %1">; +def err_pseudo_dtor_template : Error< + "specialization of template %0 does not refer to a scalar type in pseudo-" + "destructor expression">; +def err_invalid_use_of_function_type : Error< + "a function type is not allowed here">; +def err_invalid_use_of_array_type : Error<"an array type is not allowed here">; +def err_type_defined_in_condition : Error< + "types may not be defined in conditions">; +def err_typecheck_bool_condition : Error< + "value of type %0 is not contextually convertible to 'bool'">; +def err_typecheck_ambiguous_condition : Error< + "conversion from %0 to %1 is ambiguous">; +def err_typecheck_nonviable_condition : Error< + "no viable conversion from %0 to %1">; +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_invalid_declarator_global_scope : Error< + "definition or redeclaration of %0 cannot name the global scope">; +def err_invalid_declarator_in_function : Error< + "definition or redeclaration of %0 not allowed inside a function">; +def err_not_tag_in_scope : Error< + "no %select{struct|union|class|enum}0 named %1 in %2">; + +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">, + InGroup<Parentheses>; +// Completely identical except off by default. +def warn_condition_is_idiomatic_assignment : Warning<"using the result " + "of an assignment as a condition without parentheses">, + InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore; +def note_condition_assign_to_comparison : Note< + "use '==' to turn this assignment into an equality comparison">; +def note_condition_assign_silence : Note< + "place parentheses around the assignment to silence this warning">; + +def warn_value_always_zero : Warning< + "%0 is always %select{zero|false|NULL}1 in this context">; + +// assignment related diagnostics (also for argument passing, returning, etc). +// In most of these diagnostics the %2 is a value from the +// Sema::AssignmentAction enumeration +def err_typecheck_convert_incompatible : Error< + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%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">; +def warn_incompatible_qualified_id : Warning< + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%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">; +def ext_typecheck_convert_pointer_int : ExtWarn< + "incompatible pointer to integer 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">; +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">; +def ext_typecheck_convert_pointer_void_func : Extension< + "%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 " + "converts between void pointer and function pointer">; +def ext_typecheck_convert_incompatible_pointer_sign : 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 " + "converts between pointers to integer types with different sign">, + InGroup<DiagGroup<"pointer-sign">>; +def ext_typecheck_convert_incompatible_pointer : ExtWarn< + "incompatible pointer types " + "%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">; +def ext_typecheck_convert_discards_qualifiers : 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 discards " + "qualifiers">; +def ext_nested_pointer_qualifier_mismatch : 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 discards " + "qualifiers in nested pointer types">; +def warn_incompatible_vectors : Warning< + "incompatible vector types " + "%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">, + InGroup<VectorConversions>, DefaultIgnore; +def err_int_to_block_pointer : Error< + "invalid block 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">; +def err_typecheck_convert_incompatible_block_pointer : Error< + "incompatible block pointer types " + "%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">; + +def err_typecheck_convert_ambiguous : Error< + "ambiguity in initializing value of type %0 with initializer of type %1">; +def err_cannot_initialize_decl_noname : Error< + "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " + "of type %2">; +def err_cannot_initialize_decl : Error< + "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; +def err_typecheck_comparison_of_distinct_blocks : Error< + "comparison of distinct block types (%0 and %1)">; + +def err_typecheck_array_not_modifiable_lvalue : Error< + "array type %0 is not assignable">; +def err_typecheck_non_object_not_modifiable_lvalue : Error< + "non-object type %0 is not assignable">; +def err_typecheck_expression_not_modifiable_lvalue : Error< + "expression is not assignable">; +def err_typecheck_incomplete_type_not_modifiable_lvalue : Error< + "incomplete type %0 is not assignable">; +def err_typecheck_lvalue_casts_not_supported : Error< + "assignment to cast is illegal, lvalue casts are not supported">; + +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_typecheck_call_not_function : Error< + "called object type %0 is not a function or function pointer">; +def err_call_incomplete_return : Error< + "calling function with incomplete return type %0">; +def err_call_function_incomplete_return : Error< + "calling %0 with incomplete return type %1">; +def note_function_with_incomplete_return_type_declared_here : Note< + "%0 declared here">; +def err_call_incomplete_argument : Error< + "argument type %0 is incomplete">; +def err_typecheck_call_too_few_args : Error< + "too few arguments to %select{function|block|method}0 call, " + "expected %1, have %2">; +def err_typecheck_call_too_few_args_at_least : Error< + "too few arguments to %select{function|block|method}0 call, " + "expected at least %1, have %2">; +def err_typecheck_call_too_many_args : Error< + "too many arguments to %select{function|block|method}0 call, " + "expected %1, have %2">; +def err_typecheck_call_too_many_args_at_most : Error< + "too many arguments to %select{function|block|method}0 call, " + "expected at most %1, have %2">; +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< + "first argument to atomic builtin must be a pointer (%0 invalid)">; +def err_atomic_builtin_must_be_pointer_intptr : Error< + "first argument to atomic builtin must be a pointer to integer or pointer" + " (%0 invalid)">; +def err_atomic_builtin_pointer_size : Error< + "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte " + "type (%0 invalid)">; + + +def err_deleted_function_use : Error<"attempt to use a deleted function">; + +def err_cannot_pass_objc_interface_to_vararg : Error< + "cannot pass object with interface type %0 by-value through variadic " + "%select{function|block|method}1">; + +def warn_cannot_pass_non_pod_arg_to_vararg : Warning< + "cannot pass object of non-POD type %0 through variadic " + "%select{function|block|method|constructor}1; call will abort at runtime">, + InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; + +def err_typecheck_call_invalid_ordered_compare : Error< + "ordered compare requires two args of floating point type (%0 and %1)">; +def err_typecheck_call_invalid_unary_fp : Error< + "floating point classification requires argument of floating point type " + "(passed in %0)">; +def err_typecheck_cond_expect_scalar : Error< + "used type %0 where arithmetic or pointer type is required">; +def ext_typecheck_cond_one_void : Extension< + "C99 forbids conditional expressions with only one void side">; +def ext_typecheck_cast_nonscalar : Extension< + "C99 forbids casting nonscalar type %0 to the same type">; +def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">; +def err_typecheck_cast_to_union_no_type : Error< + "cast to union type from type %0 not present in union">; +def err_cast_pointer_from_non_pointer_int : Error< + "operand of type %0 cannot be cast to a pointer type">; +def err_cast_pointer_to_non_pointer_int : Error< + "pointer cannot be cast to type %0">; +def err_typecheck_expect_scalar_operand : Error< + "operand of type %0 where arithmetic or pointer type is required">; +def err_typecheck_cond_incompatible_operands : Error< + "incompatible operand types (%0 and %1)">; +def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn< + "incompatible operand types (%0 and %1) use non-standard composite pointer " + "type %2">; +def err_cast_selector_expr : Error< + "cannot type cast @selector expression">; +def warn_typecheck_cond_incompatible_pointers : ExtWarn< + "pointer type mismatch (%0 and %1)">; +def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn< + "pointer/integer type mismatch in conditional expression (%0 and %1)">; +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< + "expression result unused; should this cast be to 'void'?">, + InGroup<UnusedValue>; +def warn_unused_property_expr : Warning< + "property access result unused - getters 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>; + +def err_incomplete_type_used_in_type_trait_expr : Error< + "incomplete type %0 used in type trait expression">; +def err_expected_ident_or_lparen : Error<"expected identifier or '('">; + +} // End of general sema category. + +// inline asm. +let CategoryName = "Inline Assembly Issue" in { + def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; + def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; + def err_asm_invalid_output_constraint : Error< + "invalid output constraint '%0' in asm">; + def err_asm_invalid_lvalue_in_input : Error< + "invalid lvalue in asm input for constraint '%0'">; + def err_asm_invalid_input_constraint : Error< + "invalid input constraint '%0' in asm">; + def err_asm_invalid_type_in_input : Error< + "invalid type %0 in asm input for constraint '%1'">; + def err_asm_tying_incompatible_types : Error< + "unsupported inline asm: input with type %0 matching output with type %1">; + def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; + def err_invalid_asm_cast_lvalue : Error< + "invalid use of a cast in a inline asm context requiring an l-value: " + "remove the cast or build with -fheinous-gnu-extensions">; + + def warn_invalid_asm_cast_lvalue : Warning< + "invalid use of a cast in a inline asm context requiring an l-value: " + "accepted due to -fheinous-gnu-extensions, but clang may remove support " + "for this in the future">; +} + +let CategoryName = "Semantic Issue" in { + +def err_invalid_conversion_between_vectors : Error< + "invalid conversion between vector type %0 and %1 of different size">; +def err_invalid_conversion_between_vector_and_integer : Error< + "invalid conversion between vector type %0 and integer type %1 " + "of different size">; + +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< + "only constructors take base initializers">; + +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">; +def err_multiple_base_initialization : Error < + "multiple initializations given for base %0">; + +def err_mem_init_not_member_or_class : Error< + "member initializer %0 does not name a non-static data member or base " + "class">; + +def warn_initializer_out_of_order : Warning< + "%select{field|base class}0 %1 will be initialized after " + "%select{field|base}2 %3">, + InGroup<Reorder>, DefaultIgnore; + +def err_base_init_does_not_name_class : Error< + "constructor initializer %0 does not name a class">; +def err_base_init_direct_and_virtual : Error< + "base class initializer %0 names both a direct base class and an " + "inherited virtual base class">; +def err_not_direct_base_or_virtual : Error< + "type %0 is not a direct or virtual base of %1">; + +def err_in_class_initializer_non_integral_type : Error< + "in-class initializer has non-integral, non-enumeration type %0">; +def err_in_class_initializer_non_constant : Error< + "in-class initializer is not an integral constant expression">; + +// 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 structs are a GNU extension">, InGroup<GNU>; +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< + "anonymous union at class scope must not have a storage specifier">; +def err_anonymous_struct_not_member : Error< + "anonymous %select{structs|structs and classes}0 must be " + "%select{struct or union|class}0 members">; +def err_anonymous_union_member_redecl : Error< + "member of anonymous union redeclares %0">; +def err_anonymous_struct_member_redecl : Error< + "member of anonymous struct redeclares %0">; +def err_anonymous_record_with_type : Error< + "types cannot be declared in an anonymous %select{struct|union}0">; +def err_anonymous_record_with_function : Error< + "functions cannot be declared in an anonymous %select{struct|union}0">; +def err_anonymous_record_with_static : Error< + "static members cannot be declared in an anonymous %select{struct|union}0">; +def err_anonymous_record_bad_member : Error< + "anonymous %select{struct|union}0 can only contain non-static data members">; +def err_anonymous_record_nonpublic_member : Error< + "anonymous %select{struct|union}0 cannot contain a " + "%select{private|protected}1 data member">; + +// C++ local classes +def err_reference_to_local_var_in_enclosing_function : Error< + "reference to local variable %0 declared in enclosed function %1">; +def note_local_variable_declared_here : Note< + "%0 declared here">; +def err_static_data_member_not_allowed_in_local_class : Error< + "static data member %0 not allowed in local class %1">; + +// C++ derived classes +def err_base_clause_on_union : Error<"unions cannot have base classes">; +def err_base_must_be_class : Error<"base specifier must name a class">; +def err_union_as_base_class : Error<"unions cannot be base classes">; +def err_incomplete_base_class : Error<"base class has incomplete type">; +def err_duplicate_base_class : Error< + "base class %0 specified more than once as a direct base class">; +// FIXME: better way to display derivation? Pass entire thing into diagclient? +def err_ambiguous_derived_to_base_conv : Error< + "ambiguous conversion from derived class %0 to base class %1:%2">; +def err_ambiguous_memptr_conv : Error< + "ambiguous conversion from pointer to member of %select{base|derived}0 " + "class %1 to pointer to member of %select{derived|base}0 class %2:%3">; + +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">, NoSFINAE; +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">; +def err_ambiguous_member_multiple_subobject_types : Error< + "member %0 found in multiple base classes of different types">; +def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">; +def err_ambiguous_reference : Error<"reference to %0 is ambiguous">; +def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">; +def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a " + "declaration in a different namespace">; +def note_hidden_tag : Note<"type declaration hidden">; +def note_hiding_object : Note<"declaration hides type">; + +// C++ operator overloading +def err_operator_overload_needs_class_or_enum : Error< + "overloaded %0 must have at least one parameter of class " + "or enumeration type">; + +def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">; +def err_operator_overload_static : Error< + "overloaded %0 cannot be a static member function">; +def err_operator_overload_default_arg : Error< + "parameter of overloaded %0 cannot have a default argument">; +def err_operator_overload_must_be : Error< + "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator " + "(has %1 parameter%s1)">; + +def err_operator_overload_must_be_member : Error< + "overloaded %0 must be a non-static member function">; +def err_operator_overload_post_incdec_must_be_int : Error< + "parameter of overloaded post-%select{increment|decrement}1 operator must " + "have type 'int' (not %0)">; + +// C++ allocation and deallocation functions. +def err_operator_new_delete_declared_in_namespace : Error< + "%0 cannot be declared inside a namespace">; +def err_operator_new_delete_declared_static : Error< + "%0 cannot be declared static in global scope">; +def err_operator_new_delete_invalid_result_type : Error< + "%0 must return type %1">; +def err_operator_new_delete_dependent_result_type : Error< + "%0 cannot have a dependent return type; use %1 instead">; +def err_operator_new_delete_too_few_parameters : Error< + "%0 must have at least one parameter.">; +def err_operator_new_delete_template_too_few_parameters : Error< + "%0 template must have at least two parameters.">; + +def err_operator_new_dependent_param_type : Error< + "%0 cannot take a dependent type as first parameter; " + "use size_t (%1) instead">; +def err_operator_new_param_type : Error< + "%0 takes type size_t (%1) as first parameter">; +def err_operator_new_default_arg: Error< + "parameter of %0 cannot have a default argument">; +def err_operator_delete_dependent_param_type : Error< + "%0 cannot take a dependent type as first parameter; use %1 instead">; +def err_operator_delete_param_type : Error< + "%0 takes type %1 as first parameter">; + +// C++ literal operators +def err_literal_operator_outside_namespace : Error< + "literal operator %0 must be in a namespace or global scope">; +// FIXME: This diagnostic sucks +def err_literal_operator_params : Error< + "parameter declaration for literal operator %0 is not valid">; + +// C++ conversion functions +def err_conv_function_not_member : Error< + "conversion function must be a non-static member function">; +def err_conv_function_return_type : Error< + "conversion function cannot have a return type">; +def err_conv_function_with_params : Error< + "conversion function cannot have any parameters">; +def err_conv_function_variadic : Error< + "conversion function cannot be variadic">; +def err_conv_function_to_array : Error< + "conversion function cannot convert to an array type">; +def err_conv_function_to_function : Error< + "conversion function cannot convert to a function type">; +def err_conv_function_with_complex_decl : Error< + "must use a typedef to declare a conversion to %0">; +def err_conv_function_redeclared : Error< + "conversion function cannot be redeclared">; +def warn_conv_to_self_not_used : Warning< + "conversion function converting %0 to itself will never be used">; +def warn_conv_to_base_not_used : Warning< + "conversion function converting %0 to its base class %1 will never be used">; +def warn_conv_to_void_not_used : Warning< + "conversion function converting %0 to %1 will never be used">; + +def warn_not_compound_assign : Warning< + "use of unary operator that may be intended as compound assignment (%0=)">; + +// C++0x explicit conversion operators +def warn_explicit_conversion_functions : Warning< + "explicit conversion functions are a C++0x extension">; + +def warn_printf_write_back : Warning< + "use of '%%n' in format string discouraged (potentially insecure)">, + InGroup<FormatSecurity>; +def warn_printf_insufficient_data_args : Warning< + "more '%%' conversions than data arguments">, InGroup<Format>; +def warn_printf_data_arg_not_used : Warning< + "data argument not used by format string">, InGroup<FormatExtraArgs>; +def warn_printf_invalid_conversion : Warning< + "invalid conversion specifier '%0'">, InGroup<Format>; +def warn_printf_incomplete_specifier : Warning< + "incomplete format specifier">, InGroup<Format>; +def warn_printf_missing_format_string : Warning< + "format string missing">, InGroup<Format>; +def warn_printf_conversion_argument_type_mismatch : Warning< + "conversion 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)">, + InGroup<Format>; +def warn_printf_zero_positional_specifier : Warning< + "position arguments in format strings start counting at 1 (not 0)">, + InGroup<Format>; +def warn_printf_invalid_positional_specifier : Warning< + "invalid position specified for %select{field width|field precision}0">, + InGroup<Format>; +def warn_printf_mix_positional_nonpositional_args : Warning< + "cannot mix positional and non-positional arguments in format string">, + InGroup<Format>; +def warn_null_arg : Warning< + "null passed to a callee which requires a non-null argument">, + InGroup<NonNull>; +def warn_printf_empty_format_string : Warning< + "format string is empty">, InGroup<FormatZeroLength>; +def warn_printf_format_string_is_wide_literal : Warning< + "format string should not be a wide string">, InGroup<Format>; +def warn_printf_format_string_contains_null_char : Warning< + "format string contains '\\0' within the string body">, InGroup<Format>; +def warn_printf_asterisk_missing_arg : Warning< + "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">; +def warn_printf_asterisk_wrong_type : Warning< + "field %select{width|precision}0 should have type %1, but argument has type %2">, + InGroup<Format>; +def warn_printf_nonsensical_precision: Warning< + "precision used in '%0' conversion specifier (where it has no meaning)">, + InGroup<Format>; +def warn_printf_nonsensical_flag: Warning< + "flag '%0' results in undefined behavior in '%1' conversion specifier">, + InGroup<Format>; + +// CHECK: returning address/reference of stack memory +def warn_ret_stack_addr : Warning< + "address of stack memory associated with local variable %0 returned">; +def warn_ret_stack_ref : Warning< + "reference to stack memory associated with local variable %0 returned">; +def warn_ret_addr_label : Warning< + "returning address of label, which is local">; +def err_ret_local_block : Error< + "returning block that lives on the local stack">; + + +// For non-floating point, expressions of the form x == x or x != x +// should result in a warning, since these always evaluate to a constant. +def warn_selfcomparison : Warning< + "self-comparison always results in a constant value">; +def warn_stringcompare : Warning< + "result of comparison against %select{a string literal|@encode}0 is " + "unspecified (use strncmp instead)">; + + + +// 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_returns_array : Error< + "block declared as returning an array">; + + +// CFString checking +def err_cfstring_literal_not_string_constant : Error< + "CFString literal is not a string constant">; +def warn_cfstring_literal_contains_nul_character : Warning< + "CFString literal contains NUL character">; + +// Statements. +def err_continue_not_in_loop : Error< + "'continue' statement not in loop statement">; +def err_break_not_in_loop_or_switch : Error< + "'break' statement not in loop or switch statement">; +def err_default_not_in_switch : Error< + "'default' statement not in switch statement">; +def err_case_not_in_switch : Error<"'case' statement not in switch statement">; +def warn_bool_switch_condition : Warning< + "switch condition has boolean value">; +def warn_case_value_overflow : Warning< + "overflow converting case value to switch condition type (%0 to %1)">, + InGroup<DiagGroup<"switch">>; +def err_duplicate_case : Error<"duplicate case value '%0'">; +def warn_case_empty_range : Warning<"empty case range specified">; +def warn_missing_case_for_condition : + Warning<"no case matching constant switch condition '%0'">; +def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">, + InGroup<DiagGroup<"switch-enum"> >; +def warn_not_in_enum : Warning<"case value not in enumerated type %0">, + InGroup<DiagGroup<"switch-enum"> >; +def err_typecheck_statement_requires_scalar : Error< + "statement requires expression of scalar type (%0 invalid)">; +def err_typecheck_statement_requires_integer : Error< + "statement requires expression of integer type (%0 invalid)">; +def err_multiple_default_labels_defined : Error< + "multiple default labels in one switch">; +def err_switch_multiple_conversions : Error< + "multiple conversions from switch condition type %0 to an integral or " + "enumeration type">; +def note_switch_conversion : Note< + "conversion to %select{integral|enumeration}0 type %1">; +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 err_va_start_used_in_non_variadic_function : Error< + "'va_start' used in function with fixed args">; +def warn_second_parameter_of_va_start_not_last_named_argument : Warning< + "second parameter of 'va_start' not last named argument">; +def err_first_argument_to_va_arg_not_of_type_va_list : Error< + "first argument to 'va_arg' is of type %0 and not 'va_list'">; + +def warn_return_missing_expr : Warning< + "non-void %select{function|method}1 %0 should return a value">, + InGroup<ReturnType>; +def ext_return_missing_expr : ExtWarn< + "non-void %select{function|method}1 %0 should return a value">, + InGroup<ReturnType>; +def ext_return_has_expr : ExtWarn< + "void %select{function|method}1 %0 should not return a value">, + InGroup<ReturnType>; +def ext_return_has_void_expr : Extension< + "void %select{function|method}1 %0 should not return void expression">; +def warn_noreturn_function_has_return_expr : Warning< + "function %0 declared 'noreturn' should not return">, + InGroup<DiagGroup<"invalid-noreturn">>; +def warn_falloff_noreturn_function : Warning< + "function declared 'noreturn' should not return">, + InGroup<DiagGroup<"invalid-noreturn">>; +def err_noreturn_block_has_return_expr : Error< + "block declared 'noreturn' should not return">; +def err_block_on_nonlocal : Error< + "__block attribute not allowed, only allowed on local variables">; +def err_block_on_vm : Error< + "__block attribute not allowed on declaration with a variably modified type">; + +def err_shufflevector_non_vector : Error< + "first two arguments to __builtin_shufflevector must be vectors">; +def err_shufflevector_incompatible_vector : Error< + "first two arguments to __builtin_shufflevector must have the same type">; +def err_shufflevector_nonconstant_argument : Error< + "index for __builtin_shufflevector must be a constant integer">; +def err_shufflevector_argument_too_large : Error< + "index for __builtin_shufflevector must be less than the total number " + "of vector elements">; + +def err_vector_incorrect_num_initializers : Error< + "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; +def err_altivec_empty_initializer : Error<"expected initializer">; + +def err_argument_invalid_range : Error< + "argument should be a value from %0 to %1">; + +def err_builtin_longjmp_invalid_val : Error< + "argument to __builtin_longjmp must be a constant 1">; + +def err_constant_integer_arg_type : Error< + "argument to %0 must be a constant integer">; + +def ext_mixed_decls_code : Extension< + "ISO C90 forbids mixing declarations and code">; +def err_non_variable_decl_in_for : Error< + "declaration of non-local variable in 'for' loop">; +def err_toomany_element_decls : Error< + "only one element declaration is allowed">; +def err_selector_element_not_lvalue : Error< + "selector element is not a valid lvalue">; +def err_selector_element_type : Error< + "selector element type %0 is not a valid object">; +def err_collection_expr_type : Error< + "collection expression type %0 is not a valid object">; + +def err_invalid_conversion_between_ext_vectors : Error< + "invalid conversion between ext-vector type %0 and %1">; + +// Type +def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">; +def warn_receiver_forward_class : Warning< + "receiver %0 is a forward class and corresponding @interface may not exist">; +def note_method_sent_forward_class : Note<"method %0 is used for the forward class">; +def ext_missing_declspec : ExtWarn< + "declaration specifier missing, defaulting to 'int'">; +def ext_missing_type_specifier : ExtWarn< + "type specifier missing, defaults to 'int'">, + InGroup<ImplicitInt>; +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">; +def err_c99_array_usage_cxx : Error< + "C99-specific array features are not permitted in C++">; + +def note_getter_unavailable : Note< + "or because setter is declared here, but no getter method %0 is found">; +def err_invalid_protocol_qualifiers : Error< + "invalid protocol qualifiers on non-ObjC type">; +def warn_ivar_use_hidden : Warning< + "local declaration of %0 hides instance variable">; +def error_ivar_use_in_class_method : Error< + "instance variable %0 accessed in class method">; +def error_private_ivar_access : Error<"instance variable %0 is private">, + NoSFINAE; +def error_protected_ivar_access : Error<"instance variable %0 is protected">, + NoSFINAE; +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">; +def ext_typecheck_base_super : Warning< + "method parameter type %0 does not match " + "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore; + +// Spell-checking diagnostics +def err_unknown_typename_suggest : Error< + "unknown type name %0; did you mean %1?">; +def err_unknown_nested_typename_suggest : Error< + "no type named %0 in %1; did you mean %2?">; +def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">; +def err_undeclared_use_suggest : Error< + "use of undeclared %0; did you mean %1?">; +def err_undeclared_var_use_suggest : Error< + "use of undeclared identifier %0; did you mean %1?">; +def err_no_template_suggest : Error<"no template named %0; did you mean %1?">; +def err_no_member_template_suggest : Error< + "no template named %0 in %1; did you mean %2?">; +def err_mem_init_not_member_or_class_suggest : Error< + "initializer %0 does not name a non-static data member or base " + "class; did you mean the %select{base class|member}1 %2?">; +def err_field_designator_unknown_suggest : Error< + "field designator %0 does not refer to any field in type %1; did you mean " + "%2?">; +def err_typecheck_member_reference_ivar_suggest : Error< + "%0 does not have a member named %1; did you mean %2?">; +def err_property_not_found_suggest : Error< + "property %0 not found on object of type %1; did you mean %2?">; +def err_undef_interface_suggest : Error< + "cannot find interface declaration for %0; did you mean %1?">; +def warn_undef_interface_suggest : Warning< + "cannot find interface declaration for %0; did you mean %1?">; +def err_undef_superclass_suggest : Error< + "cannot find interface declaration for %0, superclass of %1; did you mean " + "%2?">; +def err_undeclared_protocol_suggest : Error< + "cannot find protocol declaration for %0; did you mean %1?">; +def note_base_class_specified_here : Note< + "base class %0 specified here">; + +} // end of sema category +} // end of sema component. + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h new file mode 100644 index 0000000..d0e0118 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h @@ -0,0 +1,216 @@ +//===--- FileManager.h - File System Probing and Caching --------*- 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 FileManager interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FILEMANAGER_H +#define LLVM_CLANG_FILEMANAGER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Config/config.h" // for mode_t +// FIXME: Enhance libsystem to support inode and other fields in stat. +#include <sys/types.h> +#include <sys/stat.h> + +namespace clang { +class FileManager; + +/// DirectoryEntry - Cached information about one directory on the disk. +/// +class DirectoryEntry { + const char *Name; // Name of the directory. + friend class FileManager; +public: + DirectoryEntry() : Name(0) {} + const char *getName() const { return Name; } +}; + +/// FileEntry - Cached information about one file on the disk. +/// +class FileEntry { + const char *Name; // Name of the file. + off_t Size; // File size in bytes. + time_t ModTime; // Modification time of file. + const DirectoryEntry *Dir; // Directory file lives in. + unsigned UID; // A unique (small) ID for the file. + 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'. + friend class FileManager; +public: + FileEntry(dev_t device, ino_t inode, mode_t m) + : Name(0), Device(device), Inode(inode), FileMode(m) {} + // Add a default constructor for use with llvm::StringMap + FileEntry() : Name(0), Device(0), Inode(0), FileMode(0) {} + + const char *getName() const { return Name; } + off_t getSize() const { return Size; } + unsigned getUID() const { return UID; } + ino_t getInode() const { return Inode; } + dev_t getDevice() const { return Device; } + time_t getModificationTime() const { return ModTime; } + mode_t getFileMode() const { return FileMode; } + + /// getDir - Return the directory the file lives in. + /// + const DirectoryEntry *getDir() const { return Dir; } + + bool operator<(const FileEntry& RHS) const { + return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode); + } +}; + +/// \brief Abstract interface for introducing a FileManager cache for 'stat' +/// system calls, which is used by precompiled and pretokenized headers to +/// improve performance. +class StatSysCallCache { +protected: + llvm::OwningPtr<StatSysCallCache> NextStatCache; + +public: + virtual ~StatSysCallCache() {} + virtual int stat(const char *path, struct stat *buf) { + if (getNextStatCache()) + return getNextStatCache()->stat(path, buf); + + return ::stat(path, buf); + } + + /// \brief Sets the next stat call cache in the chain of stat caches. + /// Takes ownership of the given stat cache. + void setNextStatCache(StatSysCallCache *Cache) { + NextStatCache.reset(Cache); + } + + /// \brief Retrieve the next stat call cache in the chain. + StatSysCallCache *getNextStatCache() { return NextStatCache.get(); } + + /// \brief Retrieve the next stat call cache in the chain, transferring + /// ownership of this cache (and, transitively, all of the remaining caches) + /// to the caller. + StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); } +}; + +/// \brief A stat "cache" that can be used by FileManager to keep +/// track of the results of stat() calls that occur throughout the +/// execution of the front end. +class MemorizeStatCalls : public StatSysCallCache { +public: + /// \brief The result of a stat() call. + /// + /// The first member is the result of calling stat(). If stat() + /// found something, the second member is a copy of the stat + /// structure. + typedef std::pair<int, struct stat> StatResult; + + /// \brief The set of stat() calls that have been + llvm::StringMap<StatResult, llvm::BumpPtrAllocator> StatCalls; + + typedef llvm::StringMap<StatResult, llvm::BumpPtrAllocator>::const_iterator + iterator; + + iterator begin() const { return StatCalls.begin(); } + iterator end() const { return StatCalls.end(); } + + virtual int stat(const char *path, struct stat *buf); +}; + +/// FileManager - Implements support for file system lookup, file system +/// caching, and directory search management. This also handles more advanced +/// 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 { + + class UniqueDirContainer; + class UniqueFileContainer; + + /// UniqueDirs/UniqueFiles - Cache for existing directories/files. + /// + UniqueDirContainer &UniqueDirs; + UniqueFileContainer &UniqueFiles; + + /// DirEntries/FileEntries - This is a cache of directory/file entries we have + /// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above. + /// + llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> DirEntries; + llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> FileEntries; + + /// NextFileUID - Each FileEntry we create is assigned a unique ID #. + /// + unsigned NextFileUID; + + /// \brief The virtual files that we have allocated. + llvm::SmallVector<FileEntry *, 4> VirtualFileEntries; + + // Statistics. + unsigned NumDirLookups, NumFileLookups; + unsigned NumDirCacheMisses, NumFileCacheMisses; + + // Caching. + llvm::OwningPtr<StatSysCallCache> StatCache; + + int stat_cached(const char* path, struct stat* buf) { + return StatCache.get() ? StatCache->stat(path, buf) : stat(path, buf); + } + +public: + FileManager(); + ~FileManager(); + + /// \brief Installs the provided StatSysCallCache object within + /// the FileManager. + /// + /// Ownership of this object is transferred to the FileManager. + /// + /// \param statCache the new stat cache to install. Ownership of this + /// object is transferred to the FileManager. + /// + /// \param AtBeginning whether this new stat cache must be installed at the + /// beginning of the chain of stat caches. Otherwise, it will be added to + /// the end of the chain. + void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false); + + /// \brief Removes the provided StatSysCallCache object from the file manager. + void removeStatCache(StatSysCallCache *statCache); + + /// getDirectory - Lookup, cache, and verify the specified directory. This + /// returns null if the directory doesn't exist. + /// + const DirectoryEntry *getDirectory(const llvm::StringRef &Filename) { + return getDirectory(Filename.begin(), Filename.end()); + } + const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd); + + /// getFile - Lookup, cache, and verify the specified file. This returns null + /// if the file doesn't exist. + /// + const FileEntry *getFile(const llvm::StringRef &Filename) { + return getFile(Filename.begin(), Filename.end()); + } + const FileEntry *getFile(const char *FilenameStart, + const char *FilenameEnd); + + /// \brief Retrieve a file entry for a "virtual" file that acts as + /// if there were a file with the given name on disk. The file + /// itself is not accessed. + const FileEntry *getVirtualFile(const llvm::StringRef &Filename, + off_t Size, time_t ModificationTime); + void PrintStats() const; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h new file mode 100644 index 0000000..582d59c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h @@ -0,0 +1,569 @@ +//===--- IdentifierTable.h - Hash table for identifier lookup ---*- 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 IdentifierInfo, IdentifierTable, and Selector +// interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H +#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H + +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/TokenKinds.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 <string> +#include <cassert> + +namespace llvm { + template <typename T> struct DenseMapInfo; +} + +namespace clang { + class LangOptions; + class IdentifierInfo; + class IdentifierTable; + class SourceLocation; + class MultiKeywordSelector; // private class used by Selector + class DeclarationName; // AST class that stores declaration names + + /// IdentifierLocPair - A simple pair of identifier info and location. + typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair; + + +/// IdentifierInfo - One of these records is kept for each identifier that +/// is lexed. This contains information about whether the token was #define'd, +/// is a language keyword, or if it is a front-end token of some sort (e.g. a +/// 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 > 127 won't be handled correctly. + unsigned TokenID : 8; // 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 + // are for builtins. + unsigned ObjCOrBuiltinID :10; + bool HasMacro : 1; // True if there is a #define for this. + bool IsExtension : 1; // True if identifier is a lang extension. + bool IsPoisoned : 1; // True if identifier is poisoned. + bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. + bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". + // 9 bits left in 32-bit word. + void *FETokenInfo; // Managed by the language front-end. + llvm::StringMapEntry<IdentifierInfo*> *Entry; + + IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE. + void operator=(const IdentifierInfo&); // NONASSIGNABLE. + + friend class IdentifierTable; + +public: + IdentifierInfo(); + + + /// isStr - Return true if this is the identifier for the specified string. + /// This is intended to be used for string literals only: II->isStr("foo"). + template <std::size_t StrLen> + bool isStr(const char (&Str)[StrLen]) const { + return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1); + } + + /// getNameStart - Return the beginning of the actual string for this + /// identifier. The returned string is properly null terminated. + /// + const char *getNameStart() const { + if (Entry) return Entry->getKeyData(); + // FIXME: This is gross. It would be best not to embed specific details + // of the PTH file format here. + // The 'this' pointer really points to a + // std::pair<IdentifierInfo, const char*>, where internal pointer + // points to the external string data. + return ((std::pair<IdentifierInfo, const char*>*) this)->second; + } + + /// getLength - Efficiently return the length of this identifier info. + /// + unsigned getLength() const { + if (Entry) return Entry->getKeyLength(); + // FIXME: This is gross. It would be best not to embed specific details + // of the PTH file format here. + // The 'this' pointer really points to a + // std::pair<IdentifierInfo, const char*>, where internal pointer + // points to the external string data. + const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2; + return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; + } + + /// getName - Return the actual identifier string. + llvm::StringRef getName() const { + return llvm::StringRef(getNameStart(), getLength()); + } + + /// hasMacroDefinition - Return true if this identifier is #defined to some + /// other value. + bool hasMacroDefinition() const { + return HasMacro; + } + void setHasMacroDefinition(bool Val) { + if (HasMacro == Val) return; + + HasMacro = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } + + /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API + /// can be used to cause the lexer to map identifiers to source-language + /// tokens. + tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } + void setTokenID(tok::TokenKind ID) { TokenID = ID; } + + /// getPPKeywordID - Return the preprocessor keyword ID for this identifier. + /// For example, "define" will return tok::pp_define. + tok::PPKeywordKind getPPKeywordID() const; + + /// getObjCKeywordID - Return the Objective-C keyword ID for the this + /// identifier. For example, 'class' will return tok::objc_class if ObjC is + /// enabled. + tok::ObjCKeywordKind getObjCKeywordID() const { + if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS) + return tok::ObjCKeywordKind(ObjCOrBuiltinID); + else + return tok::objc_not_keyword; + } + void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; } + + /// getBuiltinID - Return a value indicating whether this is a builtin + /// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target. + /// 2+ are specific builtin functions. + unsigned getBuiltinID() const { + if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS) + return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS; + else + return 0; + } + void setBuiltinID(unsigned ID) { + ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS; + assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID + && "ID too large for field!"); + } + + unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; } + void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; } + + /// get/setExtension - Initialize information about whether or not this + /// language token is an extension. This controls extension warnings, and is + /// only valid if a custom token ID is set. + bool isExtensionToken() const { return IsExtension; } + void setIsExtensionToken(bool Val) { + IsExtension = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } + + /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the + /// Preprocessor will emit an error every time this token is used. + void setIsPoisoned(bool Value = true) { + IsPoisoned = Value; + if (Value) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } + + /// isPoisoned - Return true if this token has been poisoned. + bool isPoisoned() const { return IsPoisoned; } + + /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether + /// this identifier is a C++ alternate representation of an operator. + void setIsCPlusPlusOperatorKeyword(bool Val = true) { + IsCPPOperatorKeyword = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } + bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } + + /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to + /// associate arbitrary metadata with this token. + template<typename T> + T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); } + void setFETokenInfo(void *T) { FETokenInfo = T; } + + /// isHandleIdentifierCase - Return true if the Preprocessor::HandleIdentifier + /// must be called on a token of this identifier. If this returns false, we + /// know that HandleIdentifier will not affect the token. + bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } + +private: + /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does + /// several special (but rare) things to identifiers of various sorts. For + /// example, it changes the "for" keyword token from tok::identifier to + /// tok::for. + /// + /// This method is very tied to the definition of HandleIdentifier. Any + /// change to it should be reflected here. + void RecomputeNeedsHandleIdentifier() { + NeedsHandleIdentifier = + (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() | + isExtensionToken()); + } +}; + +/// IdentifierInfoLookup - An abstract class used by IdentifierTable that +/// provides an interface for performing lookups from strings +/// (const char *) to IdentiferInfo objects. +class IdentifierInfoLookup { +public: + virtual ~IdentifierInfoLookup(); + + /// get - Return the identifier token info for the specified named identifier. + /// Unlike the version in IdentifierTable, this returns a pointer instead + /// of a reference. If the pointer is NULL then the IdentifierInfo cannot + /// be found. + virtual IdentifierInfo* get(llvm::StringRef Name) = 0; +}; + +/// \brief An abstract class used to resolve numerical identifier +/// references (meaningful only to some external source) into +/// IdentifierInfo pointers. +class ExternalIdentifierLookup { +public: + virtual ~ExternalIdentifierLookup(); + + /// \brief Return the identifier associated with the given ID number. + /// + /// The ID 0 is associated with the NULL identifier. + virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0; +}; + +/// IdentifierTable - This table implements an efficient mapping from strings to +/// IdentifierInfo nodes. It has no other purpose, but this is an +/// extremely performance-critical piece of the code, as each occurrance of +/// every identifier goes through here when lexed. +class IdentifierTable { + // Shark shows that using MallocAllocator is *much* slower than using this + // BumpPtrAllocator! + typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy; + HashTableTy HashTable; + + IdentifierInfoLookup* ExternalLookup; + +public: + /// IdentifierTable ctor - Create the identifier table, populating it with + /// info about the language keywords for the language specified by LangOpts. + IdentifierTable(const LangOptions &LangOpts, + IdentifierInfoLookup* externalLookup = 0); + + /// \brief Set the external identifier lookup mechanism. + void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) { + ExternalLookup = IILookup; + } + + llvm::BumpPtrAllocator& getAllocator() { + return HashTable.getAllocator(); + } + + /// get - Return the identifier token info for the specified named identifier. + /// + IdentifierInfo &get(llvm::StringRef Name) { + llvm::StringMapEntry<IdentifierInfo*> &Entry = + HashTable.GetOrCreateValue(Name); + + IdentifierInfo *II = Entry.getValue(); + if (II) return *II; + + // No entry; if we have an external lookup, look there first. + if (ExternalLookup) { + II = ExternalLookup->get(Name); + if (II) { + // Cache in the StringMap for subsequent lookups. + Entry.setValue(II); + return *II; + } + } + + // Lookups failed, make a new IdentifierInfo. + void *Mem = getAllocator().Allocate<IdentifierInfo>(); + II = new (Mem) IdentifierInfo(); + Entry.setValue(II); + + // Make sure getName() knows how to find the IdentifierInfo + // contents. + II->Entry = &Entry; + + return *II; + } + + IdentifierInfo &get(const char *NameStart, const char *NameEnd) { + return get(llvm::StringRef(NameStart, NameEnd-NameStart)); + } + + IdentifierInfo &get(const char *Name, size_t NameLen) { + return get(llvm::StringRef(Name, NameLen)); + } + + /// \brief Creates a new IdentifierInfo from the given string. + /// + /// This is a lower-level version of get() that requires that this + /// identifier not be known previously and that does not consult an + /// external source for identifiers. In particular, external + /// identifier sources can use this routine to build IdentifierInfo + /// nodes and then introduce additional information about those + /// identifiers. + IdentifierInfo &CreateIdentifierInfo(const char *NameStart, + const char *NameEnd) { + llvm::StringMapEntry<IdentifierInfo*> &Entry = + HashTable.GetOrCreateValue(NameStart, NameEnd); + + IdentifierInfo *II = Entry.getValue(); + assert(!II && "IdentifierInfo already exists"); + + // Lookups failed, make a new IdentifierInfo. + void *Mem = getAllocator().Allocate<IdentifierInfo>(); + II = new (Mem) IdentifierInfo(); + Entry.setValue(II); + + // Make sure getName() knows how to find the IdentifierInfo + // contents. + II->Entry = &Entry; + + return *II; + } + IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) { + return CreateIdentifierInfo(Name.begin(), Name.end()); + } + + typedef HashTableTy::const_iterator iterator; + typedef HashTableTy::const_iterator const_iterator; + + iterator begin() const { return HashTable.begin(); } + iterator end() const { return HashTable.end(); } + unsigned size() const { return HashTable.size(); } + + /// PrintStats - Print some statistics to stderr that indicate how well the + /// hashing is doing. + void PrintStats() const; + + void AddKeywords(const LangOptions &LangOpts); +}; + +/// Selector - This smart pointer class efficiently represents Objective-C +/// method names. This class will either point to an IdentifierInfo or a +/// MultiKeywordSelector (which is private). This enables us to optimize +/// selectors that take no arguments and selectors that take 1 argument, which +/// accounts for 78% of all selectors in Cocoa.h. +class Selector { + friend class DiagnosticInfo; + + enum IdentifierInfoFlag { + // MultiKeywordSelector = 0. + ZeroArg = 0x1, + OneArg = 0x2, + ArgFlags = ZeroArg|OneArg + }; + uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo. + + Selector(IdentifierInfo *II, unsigned nArgs) { + InfoPtr = reinterpret_cast<uintptr_t>(II); + assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); + assert(nArgs < 2 && "nArgs not equal to 0/1"); + InfoPtr |= nArgs+1; + } + Selector(MultiKeywordSelector *SI) { + InfoPtr = reinterpret_cast<uintptr_t>(SI); + assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); + } + + IdentifierInfo *getAsIdentifierInfo() const { + if (getIdentifierInfoFlag()) + return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags); + return 0; + } + unsigned getIdentifierInfoFlag() const { + return InfoPtr & ArgFlags; + } + +public: + friend class SelectorTable; // only the SelectorTable can create these + friend class DeclarationName; // and the AST's DeclarationName. + + /// The default ctor should only be used when creating data structures that + /// will contain selectors. + Selector() : InfoPtr(0) {} + Selector(uintptr_t V) : InfoPtr(V) {} + + /// operator==/!= - Indicate whether the specified selectors are identical. + bool operator==(Selector RHS) const { + return InfoPtr == RHS.InfoPtr; + } + bool operator!=(Selector RHS) const { + return InfoPtr != RHS.InfoPtr; + } + void *getAsOpaquePtr() const { + return reinterpret_cast<void*>(InfoPtr); + } + + /// \brief Determine whether this is the empty selector. + bool isNull() const { return InfoPtr == 0; } + + // Predicates to identify the selector type. + bool isKeywordSelector() const { + return getIdentifierInfoFlag() != ZeroArg; + } + bool isUnarySelector() const { + return getIdentifierInfoFlag() == ZeroArg; + } + unsigned getNumArgs() const; + IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const; + + /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return + /// it as an std::string. + std::string getAsString() const; + + static Selector getEmptyMarker() { + return Selector(uintptr_t(-1)); + } + static Selector getTombstoneMarker() { + return Selector(uintptr_t(-2)); + } +}; + +/// SelectorTable - This table allows us to fully hide how we implement +/// multi-keyword caching. +class SelectorTable { + void *Impl; // Actually a SelectorTableImpl + SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT + void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT +public: + SelectorTable(); + ~SelectorTable(); + + /// getSelector - This can create any sort of selector. NumArgs indicates + /// whether this is a no argument selector "foo", a single argument selector + /// "foo:" or multi-argument "foo:bar:". + Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV); + + Selector getUnarySelector(IdentifierInfo *ID) { + return Selector(ID, 1); + } + Selector getNullarySelector(IdentifierInfo *ID) { + return Selector(ID, 0); + } + + /// constructSetterName - Return the setter name for the given + /// identifier, i.e. "set" + Name where the initial character of Name + /// 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); + } +}; + +/// DeclarationNameExtra - Common base of the MultiKeywordSelector, +/// CXXSpecialName, and CXXOperatorIdName classes, all of which are +/// private classes that describe different kinds of names. +class DeclarationNameExtra { +public: + /// ExtraKind - The kind of "extra" information stored in the + /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of + /// how these enumerator values are used. + enum ExtraKind { + CXXConstructor = 0, + CXXDestructor, + CXXConversionFunction, +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + CXXOperator##Name, +#include "clang/Basic/OperatorKinds.def" + CXXLiteralOperator, + CXXUsingDirective, + NUM_EXTRA_KINDS + }; + + /// ExtraKindOrNumArgs - Either the kind of C++ special name or + /// operator-id (if the value is one of the CXX* enumerators of + /// ExtraKind), in which case the DeclarationNameExtra is also a + /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or + /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName, + /// it may be also name common to C++ using-directives (CXXUsingDirective), + /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of + /// arguments in the Objective-C selector, in which case the + /// DeclarationNameExtra is also a MultiKeywordSelector. + unsigned ExtraKindOrNumArgs; +}; + +} // end namespace clang + +namespace llvm { +/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and +/// DenseSets. +template <> +struct DenseMapInfo<clang::Selector> { + static inline clang::Selector getEmptyKey() { + return clang::Selector::getEmptyMarker(); + } + static inline clang::Selector getTombstoneKey() { + return clang::Selector::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::Selector S); + + static bool isEqual(clang::Selector LHS, clang::Selector RHS) { + return LHS == RHS; + } +}; + +template <> +struct isPodLike<clang::Selector> { static const bool value = true; }; + + +// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which +// are not guaranteed to be 8-byte aligned. +template<> +class PointerLikeTypeTraits<clang::IdentifierInfo*> { +public: + static inline void *getAsVoidPointer(clang::IdentifierInfo* P) { + return P; + } + static inline clang::IdentifierInfo *getFromVoidPointer(void *P) { + return static_cast<clang::IdentifierInfo*>(P); + } + enum { NumLowBitsAvailable = 1 }; +}; + +template<> +class PointerLikeTypeTraits<const clang::IdentifierInfo*> { +public: + static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) { + return P; + } + static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) { + return static_cast<const clang::IdentifierInfo*>(P); + } + enum { NumLowBitsAvailable = 1 }; +}; + +} // end namespace llvm +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h new file mode 100644 index 0000000..1ed86f1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h @@ -0,0 +1,202 @@ +//===--- LangOptions.h - C Language Family Language Options -----*- 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 LangOptions interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LANGOPTIONS_H +#define LLVM_CLANG_LANGOPTIONS_H + +#include <string> + +namespace clang { + +/// LangOptions - This class keeps track of the various options that can be +/// enabled, which controls the dialect of C that is accepted. +class LangOptions { +public: + unsigned Trigraphs : 1; // Trigraphs in source files. + unsigned BCPLComment : 1; // BCPL-style '//' comments. + unsigned Bool : 1; // 'bool', 'true', 'false' keywords. + unsigned DollarIdents : 1; // '$' allowed in identifiers. + unsigned AsmPreprocessor : 1; // Preprocessor in asm mode. + unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc) + unsigned GNUKeywords : 1; // True if GNU-only keywords are allowed + unsigned ImplicitInt : 1; // C89 implicit 'int'. + unsigned Digraphs : 1; // C94, C99 and C++ + unsigned HexFloats : 1; // C99 Hexadecimal float constants. + unsigned C99 : 1; // C99 Support + unsigned Microsoft : 1; // Microsoft extensions. + unsigned CPlusPlus : 1; // C++ Support + unsigned CPlusPlus0x : 1; // C++0x Support + unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords. + + unsigned ObjC1 : 1; // Objective-C 1 support enabled. + unsigned ObjC2 : 1; // Objective-C 2 support enabled. + unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled + unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled + + unsigned PascalStrings : 1; // Allow Pascal strings + unsigned WritableStrings : 1; // Allow writable strings + unsigned ConstStrings : 1; // Add const qualifier to strings (-Wwrite-strings) + unsigned LaxVectorConversions : 1; + unsigned AltiVec : 1; // Support AltiVec-style vector initializers. + unsigned Exceptions : 1; // Support exception handling. + unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. + unsigned RTTI : 1; // Support RTTI information. + + unsigned NeXTRuntime : 1; // Use NeXT runtime. + unsigned Freestanding : 1; // Freestanding implementation + unsigned NoBuiltin : 1; // Do not use builtin functions (-fno-builtin) + + unsigned ThreadsafeStatics : 1; // Whether static initializers are protected + // by locks. + unsigned POSIXThreads : 1; // Compiling with POSIX thread support + // (-pthread) + unsigned Blocks : 1; // block extension to C + unsigned EmitAllDecls : 1; // Emit all declarations, even if + // they are unused. + unsigned MathErrno : 1; // Math functions must respect errno + // (modulo the platform support). + + unsigned OverflowChecking : 1; // Extension to call a handler function when + // signed integer arithmetic overflows. + + unsigned HeinousExtensions : 1; // Extensions that we really don't like and + // may be ripped out at any time. + + unsigned Optimize : 1; // Whether __OPTIMIZE__ should be defined. + unsigned OptimizeSize : 1; // Whether __OPTIMIZE_SIZE__ should be + // defined. + unsigned Static : 1; // Should __STATIC__ be defined (as + // opposed to __DYNAMIC__). + unsigned PICLevel : 2; // The value for __PIC__, if non-zero. + + unsigned GNUInline : 1; // Should GNU inline semantics be + // used (instead of C99 semantics). + unsigned NoInline : 1; // Should __NO_INLINE__ be defined. + + unsigned ObjCGCBitmapPrint : 1; // Enable printing of gc's bitmap layout + // for __weak/__strong ivars. + + unsigned AccessControl : 1; // Whether C++ access control should + // be enabled. + unsigned CharIsSigned : 1; // Whether char is a signed or unsigned type + unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int. + + unsigned OpenCL : 1; // OpenCL C99 language extensions. + + unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc)) + // to the declaration of C++'s new + // operators + unsigned ElideConstructors : 1; // Whether C++ copy constructors should be + // elided if possible. + unsigned CatchUndefined : 1; // Generate code to check for undefined ops. + unsigned DumpRecordLayouts : 1; /// Dump the layout of IRgen'd records. + unsigned DumpVTableLayouts : 1; /// Dump the layouts of emitted vtables. + unsigned NoConstantCFStrings : 1; // Do not do CF strings + + // FIXME: This is just a temporary option, for testing purposes. + unsigned NoBitFieldTypeAlign : 1; + +private: + unsigned GC : 2; // Objective-C Garbage Collection modes. We + // declare this enum as unsigned because MSVC + // insists on making enums signed. Set/Query + // this value using accessors. + unsigned SymbolVisibility : 3; // Symbol's visibility. + unsigned StackProtector : 2; // Whether stack protectors are on. We declare + // this enum as unsigned because MSVC insists + // on making enums signed. Set/Query this + // value using accessors. + +public: + unsigned InstantiationDepth; // Maximum template instantiation depth. + + std::string ObjCConstantStringClass; + + enum GCMode { NonGC, GCOnly, HybridGC }; + enum StackProtectorMode { SSPOff, SSPOn, SSPReq }; + enum VisibilityMode { + Default, + Protected, + Hidden + }; + + LangOptions() { + Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; + GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0; + HexFloats = 0; + GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; + NoConstantCFStrings = 0; + C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; + CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; + Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; + NeXTRuntime = 1; + RTTI = 1; + LaxVectorConversions = 1; + HeinousExtensions = 0; + AltiVec = OpenCL = StackProtector = 0; + + SymbolVisibility = (unsigned) Default; + + ThreadsafeStatics = 1; + POSIXThreads = 0; + Blocks = 0; + EmitAllDecls = 0; + MathErrno = 1; + + AssumeSaneOperatorNew = 1; + + // FIXME: The default should be 1. + AccessControl = 0; + ElideConstructors = 1; + + OverflowChecking = 0; + ObjCGCBitmapPrint = 0; + + InstantiationDepth = 1024; + + Optimize = 0; + OptimizeSize = 0; + + Static = 0; + PICLevel = 0; + + GNUInline = 0; + NoInline = 0; + + CharIsSigned = 1; + ShortWChar = 0; + CatchUndefined = 0; + DumpRecordLayouts = 0; + DumpVTableLayouts = 0; + NoBitFieldTypeAlign = 0; + } + + GCMode getGCMode() const { return (GCMode) GC; } + void setGCMode(GCMode m) { GC = (unsigned) m; } + + StackProtectorMode getStackProtectorMode() const { + return static_cast<StackProtectorMode>(StackProtector); + } + void setStackProtectorMode(StackProtectorMode m) { + StackProtector = static_cast<unsigned>(m); + } + + VisibilityMode getVisibilityMode() const { + return (VisibilityMode) SymbolVisibility; + } + void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h new file mode 100644 index 0000000..de0de34 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h @@ -0,0 +1,57 @@ +//===--- Linkage.h - Linkage enumeration and utilities ----------*- 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 Linkage enumeration and various utility +// functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_LINKAGE_H +#define LLVM_CLANG_BASIC_LINKAGE_H + +namespace clang { + +/// \brief Describes the different kinds of linkage +/// (C++ [basic.link], C99 6.2.2) that an entity may have. +enum Linkage { + /// \brief No linkage, which means that the entity is unique and + /// can only be referred to from within its scope. + NoLinkage = 0, + + /// \brief Internal linkage, which indicates that the entity can + /// be referred to from within the translation unit (but not other + /// translation units). + InternalLinkage, + + /// \brief External linkage within a unique namespace. From the + /// langauge 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 + /// point of view. + UniqueExternalLinkage, + + /// \brief External linkage, which indicates that the entity can + /// be referred to from other translation units. + ExternalLinkage +}; + +/// \brief Determine whether the given linkage is semantically +/// external. +inline bool isExternalLinkage(Linkage L) { + return L == UniqueExternalLinkage || L == ExternalLinkage; +} + +/// \brief Compute the minimum linkage given two linages. +static inline Linkage minLinkage(Linkage L1, Linkage L2) { + return L1 < L2? L1 : L2; +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_LINKAGE_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h new file mode 100644 index 0000000..3287b30 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h @@ -0,0 +1,46 @@ +//===--- MacroBuilder.h - CPP Macro building 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 defines the MacroBuilder utility class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H +#define LLVM_CLANG_BASIC_MACROBUILDER_H + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { + +class MacroBuilder { + llvm::raw_ostream &Out; +public: + MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {} + + /// Append a #define line for macro of the form "#define Name Value\n". + void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") { + Out << "#define " << Name << ' ' << Value << '\n'; + } + + /// Append a #undef line for Name. Name should be of the form XXX + /// and we emit "#undef XXX". + void undefineMacro(const llvm::Twine &Name) { + Out << "#undef " << Name << '\n'; + } + + /// Directly append Str and a newline to the underlying buffer. + void append(const llvm::Twine &Str) { + Out << Str << '\n'; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Makefile b/contrib/llvm/tools/clang/include/clang/Basic/Makefile new file mode 100644 index 0000000..48f7f9d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Makefile @@ -0,0 +1,22 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \ + DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \ + DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \ + DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \ + DiagnosticGroups.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td) + +$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen" + $(Verb) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $< + +$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang diagnostic groups with tblgen" + $(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $< + + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h new file mode 100644 index 0000000..2019e27 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h @@ -0,0 +1,347 @@ +//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- 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 facilities for reading and writing on-disk hash +// tables. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H +#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H + +#include "llvm/Support/Allocator.h" +#include "llvm/System/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" +#include <cassert> +#include <cstdlib> + +namespace clang { + +namespace io { + +typedef uint32_t Offset; + +inline void Emit8(llvm::raw_ostream& Out, uint32_t V) { + Out << (unsigned char)(V); +} + +inline void Emit16(llvm::raw_ostream& Out, uint32_t V) { + Out << (unsigned char)(V); + Out << (unsigned char)(V >> 8); + assert((V >> 16) == 0); +} + +inline void Emit24(llvm::raw_ostream& Out, uint32_t V) { + Out << (unsigned char)(V); + Out << (unsigned char)(V >> 8); + Out << (unsigned char)(V >> 16); + assert((V >> 24) == 0); +} + +inline void Emit32(llvm::raw_ostream& Out, uint32_t V) { + Out << (unsigned char)(V); + Out << (unsigned char)(V >> 8); + Out << (unsigned char)(V >> 16); + Out << (unsigned char)(V >> 24); +} + +inline void Emit64(llvm::raw_ostream& Out, uint64_t V) { + Out << (unsigned char)(V); + Out << (unsigned char)(V >> 8); + Out << (unsigned char)(V >> 16); + Out << (unsigned char)(V >> 24); + Out << (unsigned char)(V >> 32); + Out << (unsigned char)(V >> 40); + Out << (unsigned char)(V >> 48); + Out << (unsigned char)(V >> 56); +} + +inline void Pad(llvm::raw_ostream& Out, unsigned A) { + Offset off = (Offset) Out.tell(); + uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off; + for (; n ; --n) + Emit8(Out, 0); +} + +inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) { + uint16_t V = ((uint16_t)Data[0]) | + ((uint16_t)Data[1] << 8); + Data += 2; + return V; +} + +inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) { + uint32_t V = ((uint32_t)Data[0]) | + ((uint32_t)Data[1] << 8) | + ((uint32_t)Data[2] << 16) | + ((uint32_t)Data[3] << 24); + Data += 4; + return V; +} + +inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) { + uint64_t V = ((uint64_t)Data[0]) | + ((uint64_t)Data[1] << 8) | + ((uint64_t)Data[2] << 16) | + ((uint64_t)Data[3] << 24) | + ((uint64_t)Data[4] << 32) | + ((uint64_t)Data[5] << 40) | + ((uint64_t)Data[6] << 48) | + ((uint64_t)Data[7] << 56); + Data += 8; + return V; +} + +inline uint32_t ReadLE32(const unsigned char *&Data) { + // Hosts that directly support little-endian 32-bit loads can just + // use them. Big-endian hosts need a bswap. + uint32_t V = *((uint32_t*)Data); + if (llvm::sys::isBigEndianHost()) + V = llvm::ByteSwap_32(V); + Data += 4; + return V; +} + +} // end namespace io + +template<typename Info> +class OnDiskChainedHashTableGenerator { + unsigned NumBuckets; + unsigned NumEntries; + llvm::BumpPtrAllocator BA; + + class Item { + public: + typename Info::key_type key; + typename Info::data_type data; + Item *next; + const uint32_t hash; + + Item(typename Info::key_type_ref k, typename Info::data_type_ref d) + : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {} + }; + + class Bucket { + public: + io::Offset off; + Item* head; + unsigned length; + + Bucket() {} + }; + + Bucket* Buckets; + +private: + void insert(Bucket* b, size_t size, Item* E) { + unsigned idx = E->hash & (size - 1); + Bucket& B = b[idx]; + E->next = B.head; + ++B.length; + B.head = E; + } + + void resize(size_t newsize) { + Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket)); + // Populate newBuckets with the old entries. + for (unsigned i = 0; i < NumBuckets; ++i) + for (Item* E = Buckets[i].head; E ; ) { + Item* N = E->next; + E->next = 0; + insert(newBuckets, newsize, E); + E = N; + } + + free(Buckets); + NumBuckets = newsize; + Buckets = newBuckets; + } + +public: + + void insert(typename Info::key_type_ref key, + typename Info::data_type_ref data) { + + ++NumEntries; + if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2); + insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data)); + } + + io::Offset Emit(llvm::raw_ostream &out) { + Info InfoObj; + return Emit(out, InfoObj); + } + + io::Offset Emit(llvm::raw_ostream &out, Info &InfoObj) { + using namespace clang::io; + + // Emit the payload of the table. + for (unsigned i = 0; i < NumBuckets; ++i) { + Bucket& B = Buckets[i]; + if (!B.head) continue; + + // Store the offset for the data of this bucket. + B.off = out.tell(); + assert(B.off && "Cannot write a bucket at offset 0. Please add padding."); + + // Write out the number of items in the bucket. + Emit16(out, B.length); + + // Write out the entries in the bucket. + for (Item *I = B.head; I ; I = I->next) { + Emit32(out, I->hash); + const std::pair<unsigned, unsigned>& Len = + InfoObj.EmitKeyDataLength(out, I->key, I->data); + InfoObj.EmitKey(out, I->key, Len.first); + InfoObj.EmitData(out, I->key, I->data, Len.second); + } + } + + // Emit the hashtable itself. + Pad(out, 4); + io::Offset TableOff = out.tell(); + Emit32(out, NumBuckets); + Emit32(out, NumEntries); + for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off); + + return TableOff; + } + + OnDiskChainedHashTableGenerator() { + NumEntries = 0; + NumBuckets = 64; + // Note that we do not need to run the constructors of the individual + // Bucket objects since 'calloc' returns bytes that are all 0. + Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket)); + } + + ~OnDiskChainedHashTableGenerator() { + std::free(Buckets); + } +}; + +template<typename Info> +class OnDiskChainedHashTable { + const unsigned NumBuckets; + const unsigned NumEntries; + const unsigned char* const Buckets; + const unsigned char* const Base; + Info InfoObj; + +public: + typedef typename Info::internal_key_type internal_key_type; + typedef typename Info::external_key_type external_key_type; + typedef typename Info::data_type data_type; + + OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries, + const unsigned char* buckets, + const unsigned char* base, + const Info &InfoObj = Info()) + : NumBuckets(numBuckets), NumEntries(numEntries), + Buckets(buckets), Base(base), InfoObj(InfoObj) { + assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && + "'buckets' must have a 4-byte alignment"); + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumEntries() const { return NumEntries; } + const unsigned char* getBase() const { return Base; } + const unsigned char* getBuckets() const { return Buckets; } + + bool isEmpty() const { return NumEntries == 0; } + + class iterator { + internal_key_type key; + const unsigned char* const data; + const unsigned len; + Info *InfoObj; + public: + iterator() : data(0), len(0) {} + iterator(const internal_key_type k, const unsigned char* d, unsigned l, + Info *InfoObj) + : key(k), data(d), len(l), InfoObj(InfoObj) {} + + data_type operator*() const { return InfoObj->ReadData(key, data, len); } + bool operator==(const iterator& X) const { return X.data == data; } + bool operator!=(const iterator& X) const { return X.data != data; } + }; + + iterator find(const external_key_type& eKey, Info *InfoPtr = 0) { + if (!InfoPtr) + InfoPtr = &InfoObj; + + using namespace io; + const internal_key_type& iKey = Info::GetInternalKey(eKey); + unsigned key_hash = Info::ComputeHash(iKey); + + // Each bucket is just a 32-bit offset into the hash table file. + unsigned idx = key_hash & (NumBuckets - 1); + const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx; + + unsigned offset = ReadLE32(Bucket); + if (offset == 0) return iterator(); // Empty bucket. + const unsigned char* Items = Base + offset; + + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + unsigned len = ReadUnalignedLE16(Items); + + for (unsigned i = 0; i < len; ++i) { + // Read the hash. + uint32_t item_hash = ReadUnalignedLE32(Items); + + // Determine the length of the key and the data. + const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items); + unsigned item_len = L.first + L.second; + + // Compare the hashes. If they are not the same, skip the entry entirely. + if (item_hash != key_hash) { + Items += item_len; + continue; + } + + // Read the key. + const internal_key_type& X = + InfoPtr->ReadKey((const unsigned char* const) Items, L.first); + + // If the key doesn't match just skip reading the value. + if (!Info::EqualKey(X, iKey)) { + Items += item_len; + continue; + } + + // The key matches! + return iterator(X, Items + L.first, L.second, InfoPtr); + } + + return iterator(); + } + + iterator end() const { return iterator(); } + + + static OnDiskChainedHashTable* Create(const unsigned char* buckets, + const unsigned char* const base, + const Info &InfoObj = Info()) { + using namespace io; + assert(buckets > base); + assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && + "buckets should be 4-byte aligned."); + + unsigned numBuckets = ReadLE32(buckets); + unsigned numEntries = ReadLE32(buckets); + return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets, + base, InfoObj); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def new file mode 100644 index 0000000..d011e9d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def @@ -0,0 +1,106 @@ +//===--- OperatorKinds.def - C++ Overloaded Operator 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 OverloadedOperator database, which includes +// all of the overloadable C++ operators. +// +//===----------------------------------------------------------------------===// +// +/// @file OperatorKinds.def +/// +/// In this file, each of the overloadable C++ operators is enumerated +/// with either the OVERLOADED_OPERATOR or OVERLOADED_OPERATOR_MULTI +/// macro, each of which can be specified by the code including this +/// file. OVERLOADED_OPERATOR is used for single-token operators +/// (e.g., "+"), and has six arguments: +/// +/// Name: The name of the token. OO_Name will be the name of the +/// corresponding enumerator in OverloadedOperatorKind in +/// OperatorKinds.h. +/// +/// Spelling: A string that provides a canonical spelling for the +/// operator, e.g., "operator+". +/// +/// Token: The name of the token that specifies the operator, e.g., +/// "plus" for operator+ or "greatergreaterequal" for +/// "operator>>=". With a "kw_" prefix, the token name can be used as +/// an enumerator into the TokenKind enumeration. +/// +/// Unary: True if the operator can be declared as a unary operator. +/// +/// Binary: True if the operator can be declared as a binary +/// operator. Note that some operators (e.g., "operator+" and +/// "operator*") can be both unary and binary. +/// +/// MemberOnly: True if this operator can only be declared as a +/// non-static member function. False if the operator can be both a +/// non-member function and a non-static member function. +/// +/// OVERLOADED_OPERATOR_MULTI is used to enumerate the multi-token +/// overloaded operator names, e.g., "operator delete []". The macro +/// has all of the parameters of OVERLOADED_OPERATOR except Token, +/// which is omitted. + +#ifndef OVERLOADED_OPERATOR +# define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) +#endif + +#ifndef OVERLOADED_OPERATOR_MULTI +# define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) \ + OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly) +#endif + +OVERLOADED_OPERATOR_MULTI(New , "new" , true , true , false) +OVERLOADED_OPERATOR_MULTI(Delete , "delete" , true , true , false) +OVERLOADED_OPERATOR_MULTI(Array_New , "new[]" , true , true , false) +OVERLOADED_OPERATOR_MULTI(Array_Delete , "delete[]" , true , true , false) +OVERLOADED_OPERATOR(Plus , "+" , plus , true , true , false) +OVERLOADED_OPERATOR(Minus , "-" , minus , true , true , false) +OVERLOADED_OPERATOR(Star , "*" , star , true , true , false) +OVERLOADED_OPERATOR(Slash , "/" , slash , false, true , false) +OVERLOADED_OPERATOR(Percent , "%" , percent , false, true , false) +OVERLOADED_OPERATOR(Caret , "^" , caret , false, true , false) +OVERLOADED_OPERATOR(Amp , "&" , amp , true , true , false) +OVERLOADED_OPERATOR(Pipe , "|" , pipe , false, true , false) +OVERLOADED_OPERATOR(Tilde , "~" , tilde , true , false, false) +OVERLOADED_OPERATOR(Exclaim , "!" , exclaim , true , false, false) +OVERLOADED_OPERATOR(Equal , "=" , equal , false, true , true) +OVERLOADED_OPERATOR(Less , "<" , less , false, true , false) +OVERLOADED_OPERATOR(Greater , ">" , greater , false, true , false) +OVERLOADED_OPERATOR(PlusEqual , "+=" , plusequal , false, true , false) +OVERLOADED_OPERATOR(MinusEqual , "-=" , minusequal , false, true , false) +OVERLOADED_OPERATOR(StarEqual , "*=" , starequal , false, true , false) +OVERLOADED_OPERATOR(SlashEqual , "/=" , slashequal , false, true , false) +OVERLOADED_OPERATOR(PercentEqual , "%=" , percentequal , false, true , false) +OVERLOADED_OPERATOR(CaretEqual , "^=" , caretequal , false, true , false) +OVERLOADED_OPERATOR(AmpEqual , "&=" , ampequal , false, true , false) +OVERLOADED_OPERATOR(PipeEqual , "|=" , pipeequal , false, true , false) +OVERLOADED_OPERATOR(LessLess , "<<" , lessless , false, true , false) +OVERLOADED_OPERATOR(GreaterGreater , ">>" , greatergreater , false, true , false) +OVERLOADED_OPERATOR(LessLessEqual , "<<=" , lesslessequal , false, true , false) +OVERLOADED_OPERATOR(GreaterGreaterEqual , ">>=" , greatergreaterequal, false, true , false) +OVERLOADED_OPERATOR(EqualEqual , "==" , equalequal , false, true , false) +OVERLOADED_OPERATOR(ExclaimEqual , "!=" , exclaimequal , false, true , false) +OVERLOADED_OPERATOR(LessEqual , "<=" , lessequal , false, true , false) +OVERLOADED_OPERATOR(GreaterEqual , ">=" , greaterequal , false, true , false) +OVERLOADED_OPERATOR(AmpAmp , "&&" , ampamp , false, true , false) +OVERLOADED_OPERATOR(PipePipe , "||" , pipepipe , false, true , false) +OVERLOADED_OPERATOR(PlusPlus , "++" , plusplus , true , true , false) +OVERLOADED_OPERATOR(MinusMinus , "--" , minusminus , true , true , false) +OVERLOADED_OPERATOR(Comma , "," , comma , false, true , false) +OVERLOADED_OPERATOR(ArrowStar , "->*" , arrowstar , false, true , false) +OVERLOADED_OPERATOR(Arrow , "->" , arrow , true , false, true) +OVERLOADED_OPERATOR_MULTI(Call , "()" , true , true , true) +OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, true , true) +// ?: can *not* be overloaded, but we need the overload +// resolution machinery for it. +OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false) + +#undef OVERLOADED_OPERATOR_MULTI +#undef OVERLOADED_OPERATOR diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h new file mode 100644 index 0000000..c0a9505 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h @@ -0,0 +1,35 @@ +//===--- OperatorKinds.h - C++ Overloaded Operators -------------*- 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 C++ overloaded operators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H +#define LLVM_CLANG_BASIC_OPERATOR_KINDS_H + +namespace clang { + +/// OverloadedOperatorKind - Enumeration specifying the different kinds of +/// C++ overloaded operators. +enum OverloadedOperatorKind { + OO_None, //< Not an overloaded operator +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + OO_##Name, +#include "clang/Basic/OperatorKinds.def" + NUM_OVERLOADED_OPERATORS +}; + +/// \brief Retrieve the spelling of the given overloaded operator, without +/// the preceding "operator" keyword. +const char *getOperatorSpelling(OverloadedOperatorKind Operator); + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h new file mode 100644 index 0000000..89fae87 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h @@ -0,0 +1,287 @@ +//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- 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 a partial diagnostic that can be emitted anwyhere +// in a DiagnosticBuilder stream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H +#define LLVM_CLANG_PARTIALDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/System/DataTypes.h" +#include <cassert> + +namespace clang { + +class PartialDiagnostic { +public: + struct Storage { + Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { } + + enum { + /// 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 + }; + + /// 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 + /// is mangled into an intptr_t and the intepretation depends on exactly + /// what 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. + SourceRange DiagRanges[10]; + + enum { MaxFixItHints = 3 }; + + /// FixItHints - If valid, provides a hint with some code + /// to insert, remove, or modify at a particular position. + FixItHint FixItHints[MaxFixItHints]; + }; + + /// \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 = 4; + 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; + 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 + // in the new location. + + /// 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 { + assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))); + DiagStorage = new Storage; + } + return DiagStorage; + } + + void freeStorage() { + if (!DiagStorage) + return; + + if (Allocator) + Allocator->Deallocate(DiagStorage); + else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) + delete DiagStorage; + DiagStorage = 0; + } + + void AddSourceRange(const SourceRange &R) const { + if (!DiagStorage) + DiagStorage = getStorage(); + + 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!"); + DiagStorage->FixItHints[DiagStorage->NumFixItHints++] + = Hint; + } + +public: + PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) + : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } + + PartialDiagnostic(const PartialDiagnostic &Other) + : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator) + { + if (Other.DiagStorage) { + DiagStorage = getStorage(); + *DiagStorage = *Other.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 &operator=(const PartialDiagnostic &Other) { + DiagID = Other.DiagID; + if (Other.DiagStorage) { + if (!DiagStorage) + DiagStorage = getStorage(); + + *DiagStorage = *Other.DiagStorage; + } else { + freeStorage(); + } + + return *this; + } + + ~PartialDiagnostic() { + freeStorage(); + } + + unsigned getDiagID() const { return DiagID; } + + void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { + if (!DiagStorage) + DiagStorage = getStorage(); + + assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && + "Too many arguments to diagnostic!"); + DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; + DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; + } + + void Emit(const DiagnosticBuilder &DB) const { + if (!DiagStorage) + return; + + // Add all arguments. + for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { + DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], + (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); + } + + // Add all ranges. + for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i) + DB.AddSourceRange(DiagStorage->DiagRanges[i]); + + // Add all code modification hints + for (unsigned i = 0, e = DiagStorage->NumFixItHints; 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, Diagnostic::ak_uint); + return PD; + } + + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + int I) { + PD.AddTaggedVal(I, Diagnostic::ak_sint); + return PD; + } + + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const char *S) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string); + return PD; + } + + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const SourceRange &R) { + PD.AddSourceRange(R); + return PD; + } + + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const FixItHint &Hint) { + PD.AddFixItHint(Hint); + return PD; + } + +}; + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const PartialDiagnostic &PD) { + PD.Emit(DB); + return DB; +} + + +} // end namespace clang +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h new file mode 100644 index 0000000..5a5d551 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h @@ -0,0 +1,37 @@ +//===- clang/Basic/PrettyStackTrace.h - Pretty Crash Handling --*- 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 PrettyStackTraceEntry class, which is used to make +// crashes give more contextual information about what the program was doing +// when it crashed. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H +#define CLANG_BASIC_PRETTYSTACKTRACE_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/PrettyStackTrace.h" + +namespace clang { + + /// PrettyStackTraceLoc - If a crash happens while one of these objects are + /// live, the message is printed out along with the specified source location. + class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry { + SourceManager &SM; + SourceLocation Loc; + const char *Message; + public: + PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg) + : SM(sm), Loc(L), Message(Msg) {} + virtual void print(llvm::raw_ostream &OS) const; + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h new file mode 100644 index 0000000..0bbeffe --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h @@ -0,0 +1,305 @@ +//===--- SourceLocation.h - Compact identifier for Source Files -*- 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 SourceLocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SOURCELOCATION_H +#define LLVM_CLANG_SOURCELOCATION_H + +#include <utility> +#include <cassert> + +namespace llvm { + class MemoryBuffer; + class raw_ostream; + class StringRef; + template <typename T> struct DenseMapInfo; + template <typename T> struct isPodLike; +} + +namespace clang { + +class SourceManager; + +/// FileID - This is an opaque identifier used by SourceManager which refers to +/// a source file (MemoryBuffer) along with its #include path and #line data. +/// +class FileID { + /// ID - Opaque identifier, 0 is "invalid". + unsigned ID; +public: + FileID() : ID(0) {} + + bool isInvalid() const { return ID == 0; } + + bool operator==(const FileID &RHS) const { return ID == RHS.ID; } + bool operator<(const FileID &RHS) const { return ID < RHS.ID; } + bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; } + bool operator!=(const FileID &RHS) const { return !(*this == RHS); } + bool operator>(const FileID &RHS) const { return RHS < *this; } + bool operator>=(const FileID &RHS) const { return RHS <= *this; } + + static FileID getSentinel() { return get(~0U); } + unsigned getHashValue() const { return ID; } + +private: + friend class SourceManager; + static FileID get(unsigned V) { + FileID F; + F.ID = V; + return F; + } + unsigned getOpaqueValue() const { return ID; } +}; + + +/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes +/// a full include stack, line and column number information for a position in +/// an input translation unit. +class SourceLocation { + unsigned ID; + friend class SourceManager; + enum { + MacroIDBit = 1U << 31 + }; +public: + + SourceLocation() : ID(0) {} // 0 is an invalid FileID. + + bool isFileID() const { return (ID & MacroIDBit) == 0; } + bool isMacroID() const { return (ID & MacroIDBit) != 0; } + + /// isValid - Return true if this is a valid SourceLocation object. Invalid + /// SourceLocations are often used when events have no corresponding location + /// in the source (e.g. a diagnostic is required for a command line option). + /// + bool isValid() const { return ID != 0; } + bool isInvalid() const { return ID == 0; } + +private: + /// getOffset - Return the index for SourceManager's SLocEntryTable table, + /// note that this is not an index *into* it though. + unsigned getOffset() const { + return ID & ~MacroIDBit; + } + + static SourceLocation getFileLoc(unsigned ID) { + assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); + SourceLocation L; + L.ID = ID; + return L; + } + + static SourceLocation getMacroLoc(unsigned ID) { + assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); + SourceLocation L; + L.ID = MacroIDBit | ID; + return L; + } +public: + + /// getFileLocWithOffset - Return a source location with the specified offset + /// from this file SourceLocation. + SourceLocation getFileLocWithOffset(int Offset) const { + assert(((getOffset()+Offset) & MacroIDBit) == 0 && "invalid location"); + SourceLocation L; + L.ID = ID+Offset; + return L; + } + + /// getRawEncoding - When a SourceLocation itself cannot be used, this returns + /// an (opaque) 32-bit integer encoding for it. This should only be passed + /// to SourceLocation::getFromRawEncoding, it should not be inspected + /// directly. + unsigned getRawEncoding() const { return ID; } + + + /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into + /// a real SourceLocation. + static SourceLocation getFromRawEncoding(unsigned Encoding) { + SourceLocation X; + X.ID = Encoding; + return X; + } + + void print(llvm::raw_ostream &OS, const SourceManager &SM) const; + void dump(const SourceManager &SM) const; +}; + +inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { + return LHS.getRawEncoding() == RHS.getRawEncoding(); +} + +inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { + return !(LHS == RHS); +} + +inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { + return LHS.getRawEncoding() < RHS.getRawEncoding(); +} + +/// SourceRange - a trival tuple used to represent a source range. +class SourceRange { + SourceLocation B; + SourceLocation E; +public: + SourceRange(): B(SourceLocation()), E(SourceLocation()) {} + SourceRange(SourceLocation loc) : B(loc), E(loc) {} + SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} + + SourceLocation getBegin() const { return B; } + SourceLocation getEnd() const { return E; } + + void setBegin(SourceLocation b) { B = b; } + void setEnd(SourceLocation e) { E = e; } + + bool isValid() const { return B.isValid() && E.isValid(); } + bool isInvalid() const { return !isValid(); } + + bool operator==(const SourceRange &X) const { + return B == X.B && E == X.E; + } + + bool operator!=(const SourceRange &X) const { + return B != X.B || E != X.E; + } +}; + +/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful +/// for argument passing to functions that expect both objects. +class FullSourceLoc : public SourceLocation { + const SourceManager *SrcMgr; +public: + /// Creates a FullSourceLoc where isValid() returns false. + explicit FullSourceLoc() : SrcMgr(0) {} + + explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) + : SourceLocation(Loc), SrcMgr(&SM) {} + + const SourceManager &getManager() const { + assert(SrcMgr && "SourceManager is NULL."); + return *SrcMgr; + } + + FileID getFileID() const; + + FullSourceLoc getInstantiationLoc() const; + FullSourceLoc getSpellingLoc() const; + + unsigned getInstantiationLineNumber(bool *Invalid = 0) const; + unsigned getInstantiationColumnNumber(bool *Invalid = 0) const; + + unsigned getSpellingLineNumber(bool *Invalid = 0) const; + unsigned getSpellingColumnNumber(bool *Invalid = 0) const; + + const char *getCharacterData(bool *Invalid = 0) const; + + const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const; + + /// getBufferData - Return a StringRef to the source buffer data for the + /// specified FileID. + llvm::StringRef getBufferData(bool *Invalid = 0) const; + + /// getDecomposedLoc - Decompose the specified location into a raw FileID + + /// Offset pair. The first element is the FileID, the second is the + /// offset from the start of the buffer of the location. + std::pair<FileID, unsigned> getDecomposedLoc() const; + + bool isInSystemHeader() const; + + /// Prints information about this FullSourceLoc to stderr. Useful for + /// debugging. + void dump() const { SourceLocation::dump(*SrcMgr); } + + friend inline bool + operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { + return LHS.getRawEncoding() == RHS.getRawEncoding() && + LHS.SrcMgr == RHS.SrcMgr; + } + + friend inline bool + operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { + return !(LHS == RHS); + } + +}; + +/// PresumedLoc - This class represents an unpacked "presumed" location which +/// can be presented to the user. A 'presumed' location can be modified by +/// #line and GNU line marker directives and is always the instantiation point +/// of a normal location. +/// +/// You can get a PresumedLoc from a SourceLocation with SourceManager. +class PresumedLoc { + const char *Filename; + unsigned Line, Col; + SourceLocation IncludeLoc; +public: + PresumedLoc() : Filename(0) {} + PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) + : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { + } + + /// isInvalid - Return true if this object is invalid or uninitialized. This + /// occurs when created with invalid source locations or when walking off + /// the top of a #include stack. + bool isInvalid() const { return Filename == 0; } + bool isValid() const { return Filename != 0; } + + /// getFilename - Return the presumed filename of this location. This can be + /// affected by #line etc. + const char *getFilename() const { return Filename; } + + /// getLine - Return the presumed line number of this location. This can be + /// affected by #line etc. + unsigned getLine() const { return Line; } + + /// getColumn - Return the presumed column number of this location. This can + /// not be affected by #line, but is packaged here for convenience. + unsigned getColumn() const { return Col; } + + /// getIncludeLoc - Return the presumed include location of this location. + /// This can be affected by GNU linemarker directives. + SourceLocation getIncludeLoc() const { return IncludeLoc; } +}; + + +} // end namespace clang + +namespace llvm { + /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and + /// DenseSets. + template <> + struct DenseMapInfo<clang::FileID> { + static inline clang::FileID getEmptyKey() { + return clang::FileID(); + } + static inline clang::FileID getTombstoneKey() { + return clang::FileID::getSentinel(); + } + + static unsigned getHashValue(clang::FileID S) { + return S.getHashValue(); + } + + static bool isEqual(clang::FileID LHS, clang::FileID RHS) { + return LHS == RHS; + } + }; + + template <> + struct isPodLike<clang::SourceLocation> { static const bool value = true; }; + template <> + struct isPodLike<clang::FileID> { static const bool value = true; }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h new file mode 100644 index 0000000..6a4be46 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h @@ -0,0 +1,848 @@ +//===--- SourceManager.h - Track and cache source files ---------*- 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 SourceManager interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SOURCEMANAGER_H +#define LLVM_CLANG_SOURCEMANAGER_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/Allocator.h" +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" +#include <vector> +#include <cassert> + +namespace llvm { +class MemoryBuffer; +class StringRef; +} + +namespace clang { + +class Diagnostic; +class SourceManager; +class FileManager; +class FileEntry; +class LineTableInfo; + +/// SrcMgr - Public enums and private classes that are part of the +/// SourceManager implementation. +/// +namespace SrcMgr { + /// CharacteristicKind - This is used to represent whether a file or directory + /// holds normal user code, system code, or system code which is implicitly + /// 'extern "C"' in C++ mode. Entire directories can be tagged with this + /// (this is maintained by DirectoryLookup and friends) as can specific + /// FileIDInfos when a #pragma system_header is seen or various other cases. + /// + enum CharacteristicKind { + C_User, C_System, C_ExternCSystem + }; + + /// ContentCache - Once instance of this struct is kept for every file + /// loaded or used. This object owns the MemoryBuffer object. + class ContentCache { + /// Buffer - The actual buffer containing the characters from the input + /// file. This is owned by the ContentCache object. + /// The bit indicates whether the buffer is invalid. + mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer; + + public: + /// Reference to the file entry. This reference does not own + /// the FileEntry object. It is possible for this to be NULL if + /// the ContentCache encapsulates an imaginary text buffer. + const FileEntry *Entry; + + /// SourceLineCache - A bump pointer allocated array of offsets for each + /// source line. This is lazily computed. This is owned by the + /// SourceManager BumpPointerAllocator object. + unsigned *SourceLineCache; + + /// NumLines - The number of lines in this ContentCache. This is only valid + /// if SourceLineCache is non-null. + unsigned NumLines; + + /// getBuffer - Returns the memory buffer for the associated content. + /// + /// \param Diag Object through which diagnostics will be emitted it the + /// buffer cannot be retrieved. + /// + /// \param Loc If specified, is the location that invalid file diagnostics + /// will be emitted at. + /// + /// \param Invalid If non-NULL, will be set \c true if an error occurred. + const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + const SourceManager &SM, + SourceLocation Loc = SourceLocation(), + bool *Invalid = 0) const; + + /// getSize - Returns the size of the content encapsulated by this + /// ContentCache. This can be the size of the source file or the size of an + /// arbitrary scratch buffer. If the ContentCache encapsulates a source + /// file this size is retrieved from the file's FileEntry. + unsigned getSize() const; + + /// getSizeBytesMapped - Returns the number of bytes actually mapped for + /// this ContentCache. This can be 0 if the MemBuffer was not actually + /// instantiated. + unsigned getSizeBytesMapped() const; + + void setBuffer(const llvm::MemoryBuffer *B) { + assert(!Buffer.getPointer() && "MemoryBuffer already set."); + Buffer.setPointer(B); + Buffer.setInt(false); + } + + /// \brief Replace the existing buffer (which will be deleted) + /// with the given buffer. + void replaceBuffer(const llvm::MemoryBuffer *B); + + ContentCache(const FileEntry *Ent = 0) + : Buffer(0, false), Entry(Ent), 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 transfered, so this is a logical error. + ContentCache(const ContentCache &RHS) + : Buffer(0, false), SourceLineCache(0) + { + Entry = RHS.Entry; + + 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); + }; + + /// FileInfo - Information about a FileID, basically just the logical file + /// that it represents and include stack information. + /// + /// Each FileInfo has include stack information, indicating where it came + /// from. This information encodes the #include chain that a token was + /// instantiated from. The main include file has an invalid IncludeLoc. + /// + /// FileInfos contain a "ContentCache *", with the contents of the file. + /// + class FileInfo { + /// IncludeLoc - The location of the #include that brought in this file. + /// This is an invalid SLOC for the main file (top of the #include chain). + unsigned IncludeLoc; // Really a SourceLocation + + /// Data - This contains the ContentCache* and the bits indicating the + /// characteristic of the file and whether it has #line info, all bitmangled + /// together. + uintptr_t Data; + public: + /// get - Return a FileInfo object. + static FileInfo get(SourceLocation IL, const ContentCache *Con, + CharacteristicKind FileCharacter) { + FileInfo X; + X.IncludeLoc = IL.getRawEncoding(); + X.Data = (uintptr_t)Con; + assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned"); + assert((unsigned)FileCharacter < 4 && "invalid file character"); + X.Data |= (unsigned)FileCharacter; + return X; + } + + SourceLocation getIncludeLoc() const { + return SourceLocation::getFromRawEncoding(IncludeLoc); + } + const ContentCache* getContentCache() const { + return reinterpret_cast<const ContentCache*>(Data & ~7UL); + } + + /// getCharacteristic - Return whether this is a system header or not. + CharacteristicKind getFileCharacteristic() const { + return (CharacteristicKind)(Data & 3); + } + + /// hasLineDirectives - Return true if this FileID has #line directives in + /// it. + bool hasLineDirectives() const { return (Data & 4) != 0; } + + /// setHasLineDirectives - Set the flag that indicates that this FileID has + /// line table entries associated with it. + void setHasLineDirectives() { + Data |= 4; + } + }; + + /// InstantiationInfo - Each InstantiationInfo encodes the Instantiation + /// location - where the token was ultimately instantiated, and the + /// SpellingLoc - where the actual character data for the token came from. + class InstantiationInfo { + // Really these are all SourceLocations. + + /// SpellingLoc - Where the spelling for the token can be found. + unsigned SpellingLoc; + + /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these + /// indicate the start and end of the instantiation. In object-like macros, + /// these will be the same. In a function-like macro instantiation, the + /// start will be the identifier and the end will be the ')'. + unsigned InstantiationLocStart, InstantiationLocEnd; + public: + SourceLocation getSpellingLoc() const { + return SourceLocation::getFromRawEncoding(SpellingLoc); + } + SourceLocation getInstantiationLocStart() const { + return SourceLocation::getFromRawEncoding(InstantiationLocStart); + } + SourceLocation getInstantiationLocEnd() const { + return SourceLocation::getFromRawEncoding(InstantiationLocEnd); + } + + std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const { + return std::make_pair(getInstantiationLocStart(), + getInstantiationLocEnd()); + } + + /// get - Return a InstantiationInfo for an expansion. IL specifies + /// the instantiation location (where the macro is expanded), and SL + /// specifies the spelling location (where the characters from the token + /// come from). IL and PL can both refer to normal File SLocs or + /// instantiation locations. + static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd, + SourceLocation SL) { + InstantiationInfo X; + X.SpellingLoc = SL.getRawEncoding(); + X.InstantiationLocStart = ILStart.getRawEncoding(); + X.InstantiationLocEnd = ILEnd.getRawEncoding(); + return X; + } + }; + + /// SLocEntry - This is a discriminated union of FileInfo and + /// InstantiationInfo. SourceManager keeps an array of these objects, and + /// they are uniquely identified by the FileID datatype. + class SLocEntry { + unsigned Offset; // low bit is set for instantiation info. + union { + FileInfo File; + InstantiationInfo Instantiation; + }; + public: + unsigned getOffset() const { return Offset >> 1; } + + bool isInstantiation() const { return Offset & 1; } + bool isFile() const { return !isInstantiation(); } + + const FileInfo &getFile() const { + assert(isFile() && "Not a file SLocEntry!"); + return File; + } + + const InstantiationInfo &getInstantiation() const { + assert(isInstantiation() && "Not an instantiation SLocEntry!"); + return Instantiation; + } + + static SLocEntry get(unsigned Offset, const FileInfo &FI) { + SLocEntry E; + E.Offset = Offset << 1; + E.File = FI; + return E; + } + + static SLocEntry get(unsigned Offset, const InstantiationInfo &II) { + SLocEntry E; + E.Offset = (Offset << 1) | 1; + E.Instantiation = II; + return E; + } + }; +} // end SrcMgr namespace. + +/// \brief External source of source location entries. +class ExternalSLocEntrySource { +public: + virtual ~ExternalSLocEntrySource(); + + /// \brief Read the source location entry with index ID. + virtual void ReadSLocEntry(unsigned ID) = 0; +}; + + +/// IsBeforeInTranslationUnitCache - This class holds the cache used by +/// isBeforeInTranslationUnit. The cache structure is complex enough to be +/// worth breaking out of SourceManager. +class IsBeforeInTranslationUnitCache { + /// L/R QueryFID - These are the FID's of the cached query. If these match up + /// with a subsequent query, the result can be reused. + FileID LQueryFID, RQueryFID; + + /// CommonFID - This is the file found in common between the two #include + /// traces. It is the nearest common ancestor of the #include tree. + FileID CommonFID; + + /// L/R CommonOffset - This is the offset of the previous query in CommonFID. + /// Usually, this represents the location of the #include for QueryFID, but if + /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a + /// random token in the parent. + unsigned LCommonOffset, RCommonOffset; +public: + + /// isCacheValid - Return true if the currently cached values match up with + /// the specified LHS/RHS query. If not, we can't use the cache. + bool isCacheValid(FileID LHS, FileID RHS) const { + return LQueryFID == LHS && RQueryFID == RHS; + } + + /// getCachedResult - If the cache is valid, compute the result given the + /// specified offsets in the LHS/RHS FID's. + bool getCachedResult(unsigned LOffset, unsigned ROffset) const { + // If one of the query files is the common file, use the offset. Otherwise, + // use the #include loc in the common file. + if (LQueryFID != CommonFID) LOffset = LCommonOffset; + if (RQueryFID != CommonFID) ROffset = RCommonOffset; + return LOffset < ROffset; + } + + // Set up a new query. + void setQueryFIDs(FileID LHS, FileID RHS) { + LQueryFID = LHS; + RQueryFID = RHS; + } + + void setCommonLoc(FileID commonFID, unsigned lCommonOffset, + unsigned rCommonOffset) { + CommonFID = commonFID; + LCommonOffset = lCommonOffset; + RCommonOffset = rCommonOffset; + } + +}; + +/// SourceManager - This file handles loading and caching of source files into +/// memory. This object owns the MemoryBuffer objects for all of the loaded +/// files and assigns unique FileID's for each unique #include chain. +/// +/// The SourceManager can be queried for information about SourceLocation +/// objects, turning them into either spelling or instantiation locations. +/// Spelling locations represent where the bytes corresponding to a token came +/// from and instantiation locations represent where the location is in the +/// user's view. In the case of a macro expansion, for example, the spelling +/// location indicates where the expanded token came from and the instantiation +/// location specifies where it was expanded. +class SourceManager { + /// \brief Diagnostic object. + Diagnostic &Diag; + + mutable llvm::BumpPtrAllocator ContentCacheAlloc; + + /// FileInfos - Memoized information about all of the files tracked by this + /// SourceManager. This set allows us to merge ContentCache entries based + /// on their FileEntry*. All ContentCache objects will thus have unique, + /// non-null, FileEntry pointers. + llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; + + /// MemBufferInfos - Information about various memory buffers that we have + /// read in. All FileEntry* within the stored ContentCache objects are NULL, + /// as they do not refer to a file. + std::vector<SrcMgr::ContentCache*> MemBufferInfos; + + /// SLocEntryTable - This is an array of SLocEntry's that we have created. + /// FileID is an index into this vector. This array is sorted by the offset. + std::vector<SrcMgr::SLocEntry> SLocEntryTable; + /// NextOffset - This is the next available offset that a new SLocEntry can + /// start at. It is SLocEntryTable.back().getOffset()+size of back() entry. + unsigned NextOffset; + + /// \brief If source location entries are being lazily loaded from + /// an external source, this vector indicates whether the Ith source + /// location entry has already been loaded from the external storage. + std::vector<bool> SLocEntryLoaded; + + /// \brief An external source for source location entries. + ExternalSLocEntrySource *ExternalSLocEntries; + + /// LastFileIDLookup - This is a one-entry cache to speed up getFileID. + /// LastFileIDLookup records the last FileID looked up or created, because it + /// is very common to look up many tokens from the same file. + mutable FileID LastFileIDLookup; + + /// LineTable - This holds information for #line directives. It is referenced + /// by indices from SLocEntryTable. + LineTableInfo *LineTable; + + /// LastLineNo - These ivars serve as a cache used in the getLineNumber + /// method which is used to speedup getLineNumber calls to nearby locations. + mutable FileID LastLineNoFileIDQuery; + mutable SrcMgr::ContentCache *LastLineNoContentCache; + mutable unsigned LastLineNoFilePos; + mutable unsigned LastLineNoResult; + + /// MainFileID - The file ID for the main source file of the translation unit. + FileID MainFileID; + + // Statistics for -print-stats. + mutable unsigned NumLinearScans, NumBinaryProbes; + + // Cache results for the isBeforeInTranslationUnit method. + mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; + + // SourceManager doesn't support copy construction. + explicit SourceManager(const SourceManager&); + void operator=(const SourceManager&); +public: + SourceManager(Diagnostic &Diag) + : Diag(Diag), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), + NumBinaryProbes(0) { + clearIDTables(); + } + ~SourceManager(); + + void clearIDTables(); + + //===--------------------------------------------------------------------===// + // MainFileID creation and querying methods. + //===--------------------------------------------------------------------===// + + /// getMainFileID - Returns the FileID of the main source file. + FileID getMainFileID() const { return MainFileID; } + + /// createMainFileID - Create the FileID for the main source file. + FileID createMainFileID(const FileEntry *SourceFile, + SourceLocation IncludePos) { + assert(MainFileID.isInvalid() && "MainFileID already set!"); + MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User); + return MainFileID; + } + + //===--------------------------------------------------------------------===// + // Methods to create new FileID's and instantiations. + //===--------------------------------------------------------------------===// + + /// createFileID - Create a new FileID that represents the specified file + /// being #included from the specified IncludePosition. This returns 0 on + /// error and translates NULL into standard input. + /// PreallocateID should be non-zero to specify which a pre-allocated, + /// lazily computed source location is being filled in by this operation. + FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, + SrcMgr::CharacteristicKind FileCharacter, + unsigned PreallocatedID = 0, + unsigned Offset = 0) { + const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); + if (IR == 0) return FileID(); // Error opening file? + return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset); + } + + /// createFileIDForMemBuffer - Create a new FileID that represents the + /// 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, + unsigned PreallocatedID = 0, + unsigned Offset = 0) { + return createFileID(createMemBufferContentCache(Buffer), SourceLocation(), + SrcMgr::C_User, PreallocatedID, Offset); + } + + /// createMainFileIDForMembuffer - Create the FileID for a memory buffer + /// that will represent the FileID for the main source. One example + /// of when this would be used is when the main source is read from STDIN. + FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { + assert(MainFileID.isInvalid() && "MainFileID already set!"); + MainFileID = createFileIDForMemBuffer(Buffer); + return MainFileID; + } + + /// createInstantiationLoc - Return a new SourceLocation that encodes the fact + /// that a token at Loc should actually be referenced from InstantiationLoc. + /// TokLength is the length of the token being instantiated. + SourceLocation createInstantiationLoc(SourceLocation Loc, + SourceLocation InstantiationLocStart, + SourceLocation InstantiationLocEnd, + unsigned TokLength, + unsigned PreallocatedID = 0, + unsigned Offset = 0); + + /// \brief Retrieve the memory buffer associated with the given file. + /// + /// \param Invalid If non-NULL, will be set \c true if an error + /// occurs while retrieving the memory buffer. + const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File, + bool *Invalid = 0); + + /// \brief Override the contents of the given source file by providing an + /// already-allocated buffer. + /// + /// \param SourceFile the source file whose contents will be override. + /// + /// \param Buffer the memory buffer whose contents will be used as the + /// data in the given source file. + /// + /// \returns true if an error occurred, false otherwise. + bool overrideFileContents(const FileEntry *SourceFile, + const llvm::MemoryBuffer *Buffer); + + //===--------------------------------------------------------------------===// + // FileID manipulation methods. + //===--------------------------------------------------------------------===// + + /// getBuffer - Return the buffer for the specified FileID. If there is an + /// error opening this buffer the first time, this manufactures a temporary + /// buffer and returns a non-empty error string. + const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, + bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, Loc, Invalid); + } + + const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, SourceLocation(), Invalid); + } + + /// getFileEntryForID - Returns the FileEntry record for the provided FileID. + const FileEntry *getFileEntryForID(FileID FID) const { + return getSLocEntry(FID).getFile().getContentCache()->Entry; + } + + /// getBufferData - Return a StringRef to the source buffer data for the + /// specified FileID. + /// + /// \param FID The file ID whose contents will be returned. + /// \param Invalid If non-NULL, will be set true if an error occurred. + llvm::StringRef getBufferData(FileID FID, bool *Invalid = 0) const; + + + //===--------------------------------------------------------------------===// + // SourceLocation manipulation methods. + //===--------------------------------------------------------------------===// + + /// getFileID - Return the FileID for a SourceLocation. This is a very + /// hot method that is used for all SourceManager queries that start with a + /// SourceLocation object. It is responsible for finding the entry in + /// SLocEntryTable which contains the specified location. + /// + FileID getFileID(SourceLocation SpellingLoc) const { + unsigned SLocOffset = SpellingLoc.getOffset(); + + // If our one-entry cache covers this offset, just return it. + if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) + return LastFileIDLookup; + + return getFileIDSlow(SLocOffset); + } + + /// getLocForStartOfFile - Return the source location corresponding to the + /// first byte of the specified file. + SourceLocation getLocForStartOfFile(FileID FID) const { + assert(FID.ID < SLocEntryTable.size() && "FileID out of range"); + assert(getSLocEntry(FID).isFile() && "FileID is not a file"); + unsigned FileOffset = getSLocEntry(FID).getOffset(); + return SourceLocation::getFileLoc(FileOffset); + } + + /// getInstantiationLoc - Given a SourceLocation object, return the + /// instantiation location referenced by the ID. + SourceLocation getInstantiationLoc(SourceLocation Loc) const { + // Handle the non-mapped case inline, defer to out of line code to handle + // instantiations. + if (Loc.isFileID()) return Loc; + return getInstantiationLocSlowCase(Loc); + } + + /// getImmediateInstantiationRange - Loc is required to be an instantiation + /// location. Return the start/end of the instantiation information. + std::pair<SourceLocation,SourceLocation> + getImmediateInstantiationRange(SourceLocation Loc) const; + + /// getInstantiationRange - Given a SourceLocation object, return the + /// range of tokens covered by the instantiation in the ultimate file. + std::pair<SourceLocation,SourceLocation> + getInstantiationRange(SourceLocation Loc) const; + + + /// getSpellingLoc - Given a SourceLocation object, return the spelling + /// location referenced by the ID. This is the place where the characters + /// that make up the lexed token can be found. + SourceLocation getSpellingLoc(SourceLocation Loc) const { + // Handle the non-mapped case inline, defer to out of line code to handle + // instantiations. + if (Loc.isFileID()) return Loc; + return getSpellingLocSlowCase(Loc); + } + + /// getImmediateSpellingLoc - Given a SourceLocation object, return the + /// spelling location referenced by the ID. This is the first level down + /// towards the place where the characters that make up the lexed token can be + /// found. This should not generally be used by clients. + SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; + + /// getDecomposedLoc - Decompose the specified location into a raw FileID + + /// Offset pair. The first element is the FileID, the second is the + /// 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()); + } + + /// getDecomposedInstantiationLoc - Decompose the specified location into a + /// raw FileID + Offset pair. If the location is an instantiation record, + /// walk through it until we find the final location instantiated. + std::pair<FileID, unsigned> + getDecomposedInstantiationLoc(SourceLocation Loc) const { + FileID FID = getFileID(Loc); + const SrcMgr::SLocEntry *E = &getSLocEntry(FID); + + unsigned Offset = Loc.getOffset()-E->getOffset(); + if (Loc.isFileID()) + return std::make_pair(FID, Offset); + + return getDecomposedInstantiationLocSlowCase(E, Offset); + } + + /// getDecomposedSpellingLoc - Decompose the specified location into a raw + /// FileID + Offset pair. If the location is an instantiation record, walk + /// through it until we find its spelling record. + std::pair<FileID, unsigned> + getDecomposedSpellingLoc(SourceLocation Loc) const { + FileID FID = getFileID(Loc); + const SrcMgr::SLocEntry *E = &getSLocEntry(FID); + + unsigned Offset = Loc.getOffset()-E->getOffset(); + if (Loc.isFileID()) + return std::make_pair(FID, Offset); + return getDecomposedSpellingLocSlowCase(E, Offset); + } + + /// getFileOffset - This method returns the offset from the start + /// of the file that the specified SourceLocation represents. This is not very + /// meaningful for a macro ID. + unsigned getFileOffset(SourceLocation SpellingLoc) const { + return getDecomposedLoc(SpellingLoc).second; + } + + + //===--------------------------------------------------------------------===// + // Queries about the code at a SourceLocation. + //===--------------------------------------------------------------------===// + + /// getCharacterData - Return a pointer to the start of the specified location + /// in the appropriate spelling MemoryBuffer. + /// + /// \param Invalid If non-NULL, will be set \c true if an error occurs. + const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const; + + /// getColumnNumber - Return the column # for the specified file position. + /// This is significantly cheaper to compute than the line number. This + /// returns zero if the column number isn't known. This may only be called on + /// a file sloc, so you must choose a spelling or instantiation location + /// before calling this method. + unsigned getColumnNumber(FileID FID, unsigned FilePos, + bool *Invalid = 0) const; + unsigned getSpellingColumnNumber(SourceLocation Loc, + bool *Invalid = 0) const; + unsigned getInstantiationColumnNumber(SourceLocation Loc, + bool *Invalid = 0) const; + + + /// getLineNumber - Given a SourceLocation, return the spelling line number + /// for the position indicated. This requires building and caching a table of + /// line offsets for the MemoryBuffer, so this is not cheap: use only when + /// about to emit a diagnostic. + unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const; + + unsigned getInstantiationLineNumber(SourceLocation Loc, + bool *Invalid = 0) const; + unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const; + + /// Return the filename or buffer identifier of the buffer the location is in. + /// Note that this name does not respect #line directives. Use getPresumedLoc + /// for normal clients. + const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const; + + /// getFileCharacteristic - return the file characteristic of the specified + /// source location, indicating whether this is a normal file, a system + /// header, or an "implicit extern C" system header. + /// + /// This state can be modified with flags on GNU linemarker directives like: + /// # 4 "foo.h" 3 + /// which changes all source locations in the current file after that to be + /// considered to be from a system header. + SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; + + /// getPresumedLoc - This method returns the "presumed" location of a + /// SourceLocation specifies. A "presumed location" can be modified by #line + /// or GNU line marker directives. This provides a view on the data that a + /// user should see in diagnostics, for example. + /// + /// Note that a presumed location is always given as the instantiation point + /// of an instantiation location, not at the spelling location. + PresumedLoc getPresumedLoc(SourceLocation Loc) const; + + /// isFromSameFile - Returns true if both SourceLocations correspond to + /// the same file. + bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const { + return getFileID(Loc1) == getFileID(Loc2); + } + + /// isFromMainFile - Returns true if the file of provided SourceLocation is + /// the main file. + bool isFromMainFile(SourceLocation Loc) const { + return getFileID(Loc) == getMainFileID(); + } + + /// isInSystemHeader - Returns if a SourceLocation is in a system header. + bool isInSystemHeader(SourceLocation Loc) const { + return getFileCharacteristic(Loc) != SrcMgr::C_User; + } + + /// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C" + /// system header. + bool isInExternCSystemHeader(SourceLocation Loc) const { + return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; + } + + //===--------------------------------------------------------------------===// + // Line Table Manipulation Routines + //===--------------------------------------------------------------------===// + + /// getLineTableFilenameID - Return the uniqued ID for the specified filename. + /// + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + + /// AddLineNote - Add a line note to the line table for the FileID and offset + /// specified by Loc. If FilenameID is -1, it is considered to be + /// unspecified. + void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID); + void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, + bool IsFileEntry, bool IsFileExit, + bool IsSystemHeader, bool IsExternCHeader); + + /// \brief Determine if the source manager has a line table. + bool hasLineTable() const { return LineTable != 0; } + + /// \brief Retrieve the stored line table. + LineTableInfo &getLineTable(); + + //===--------------------------------------------------------------------===// + // Other miscellaneous methods. + //===--------------------------------------------------------------------===// + + /// \brief Get the source location for the given file:line:col triplet. + /// + /// If the source file is included multiple times, the source location will + /// be based upon the first inclusion. + SourceLocation getLocation(const FileEntry *SourceFile, + unsigned Line, unsigned Col) const; + + /// \brief Determines the order of 2 source locations in the translation unit. + /// + /// \returns true if LHS source location comes before RHS, false otherwise. + bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; + + // Iterators over FileInfos. + typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> + ::const_iterator fileinfo_iterator; + fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } + fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } + bool hasFileInfo(const FileEntry *File) const { + return FileInfos.find(File) != FileInfos.end(); + } + + /// PrintStats - Print statistics to stderr. + /// + void PrintStats() const; + + unsigned sloc_entry_size() const { return SLocEntryTable.size(); } + + // FIXME: Exposing this is a little gross; what we want is a good way + // to iterate the entries that were not defined in a PCH file (or + // any other external source). + unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } + + const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { + assert(ID < SLocEntryTable.size() && "Invalid id"); + if (ExternalSLocEntries && + ID < SLocEntryLoaded.size() && + !SLocEntryLoaded[ID]) + ExternalSLocEntries->ReadSLocEntry(ID); + return SLocEntryTable[ID]; + } + + const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { + return getSLocEntry(FID.ID); + } + + unsigned getNextOffset() const { return NextOffset; } + + /// \brief Preallocate some number of source location entries, which + /// will be loaded as needed from the given external source. + void PreallocateSLocEntries(ExternalSLocEntrySource *Source, + unsigned NumSLocEntries, + unsigned NextOffset); + + /// \brief Clear out any preallocated source location entries that + /// haven't already been loaded. + void ClearPreallocatedSLocEntries(); + +private: + /// isOffsetInFileID - Return true if the specified FileID contains the + /// specified SourceLocation offset. This is a very hot method. + inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); + // If the entry is after the offset, it can't contain it. + if (SLocOffset < Entry.getOffset()) return false; + + // If this is the last entry than it does. Otherwise, the entry after it + // has to not include it. + if (FID.ID+1 == SLocEntryTable.size()) return true; + + return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset(); + } + + /// createFileID - Create a new fileID for the specified ContentCache and + /// include position. This works regardless of whether the ContentCache + /// corresponds to a file or some other input source. + FileID createFileID(const SrcMgr::ContentCache* File, + SourceLocation IncludePos, + SrcMgr::CharacteristicKind DirCharacter, + unsigned PreallocatedID = 0, + unsigned Offset = 0); + + const SrcMgr::ContentCache * + getOrCreateContentCache(const FileEntry *SourceFile); + + /// createMemBufferContentCache - Create a new ContentCache for the specified + /// memory buffer. + const SrcMgr::ContentCache* + createMemBufferContentCache(const llvm::MemoryBuffer *Buf); + + FileID getFileIDSlow(unsigned SLocOffset) const; + + SourceLocation getInstantiationLocSlowCase(SourceLocation Loc) const; + SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; + + std::pair<FileID, unsigned> + getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, + unsigned Offset) const; + std::pair<FileID, unsigned> + getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, + unsigned Offset) const; +}; + + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h new file mode 100644 index 0000000..258989c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h @@ -0,0 +1,130 @@ +//===--- SourceManagerInternals.h - SourceManager Internals -----*- 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 implementation details of the SourceManager +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H +#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H + +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringMap.h" +#include <map> + +namespace clang { + +//===----------------------------------------------------------------------===// +// Line Table Implementation +//===----------------------------------------------------------------------===// + +struct LineEntry { + /// FileOffset - The offset in this file that the line entry occurs at. + unsigned FileOffset; + + /// LineNo - The presumed line number of this line entry: #line 4. + unsigned LineNo; + + /// FilenameID - The ID of the filename identified by this line entry: + /// #line 4 "foo.c". This is -1 if not specified. + int FilenameID; + + /// Flags - Set the 0 if no flags, 1 if a system header, + SrcMgr::CharacteristicKind FileKind; + + /// IncludeOffset - This is the offset of the virtual include stack location, + /// which is manipulated by GNU linemarker directives. If this is 0 then + /// there is no virtual #includer. + unsigned IncludeOffset; + + static LineEntry get(unsigned Offs, unsigned Line, int Filename, + SrcMgr::CharacteristicKind FileKind, + unsigned IncludeOffset) { + LineEntry E; + E.FileOffset = Offs; + E.LineNo = Line; + E.FilenameID = Filename; + E.FileKind = FileKind; + E.IncludeOffset = IncludeOffset; + return E; + } +}; + +// needed for FindNearestLineEntry (upper_bound of LineEntry) +inline bool operator<(const LineEntry &lhs, const LineEntry &rhs) { + // FIXME: should check the other field? + return lhs.FileOffset < rhs.FileOffset; +} + +inline bool operator<(const LineEntry &E, unsigned Offset) { + return E.FileOffset < Offset; +} + +inline bool operator<(unsigned Offset, const LineEntry &E) { + return Offset < E.FileOffset; +} + +/// LineTableInfo - This class is used to hold and unique data used to +/// represent #line information. +class LineTableInfo { + /// FilenameIDs - This map is used to assign unique IDs to filenames in + /// #line directives. This allows us to unique the filenames that + /// frequently reoccur and reference them with indices. FilenameIDs holds + /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID + /// to string. + llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs; + std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID; + + /// LineEntries - This is a map from FileIDs to a list of line entries (sorted + /// by the offset they occur in the file. + std::map<unsigned, std::vector<LineEntry> > LineEntries; +public: + LineTableInfo() { + } + + void clear() { + FilenameIDs.clear(); + FilenamesByID.clear(); + LineEntries.clear(); + } + + ~LineTableInfo() {} + + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + const char *getFilename(unsigned ID) const { + assert(ID < FilenamesByID.size() && "Invalid FilenameID"); + return FilenamesByID[ID]->getKeyData(); + } + unsigned getNumFilenames() const { return FilenamesByID.size(); } + + void AddLineNote(unsigned FID, unsigned Offset, + unsigned LineNo, int FilenameID); + void AddLineNote(unsigned FID, unsigned Offset, + unsigned LineNo, int FilenameID, + unsigned EntryExit, SrcMgr::CharacteristicKind FileKind); + + + /// FindNearestLineEntry - Find the line entry nearest to FID that is before + /// it. If there is no line entry before Offset in FID, return null. + const LineEntry *FindNearestLineEntry(unsigned FID, unsigned Offset); + + // Low-level access + typedef std::map<unsigned, std::vector<LineEntry> >::iterator iterator; + iterator begin() { return LineEntries.begin(); } + iterator end() { return LineEntries.end(); } + + /// \brief Add a new line entry that has already been encoded into + /// the internal representation of the line table. + void AddEntry(unsigned FID, const std::vector<LineEntry> &Entries); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h new file mode 100644 index 0000000..9e54762a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h @@ -0,0 +1,83 @@ +//===--- Specifiers.h - Declaration and Type Specifiers ---------*- 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 various enumerations that describe declaration and +// type specifiers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H +#define LLVM_CLANG_BASIC_SPECIFIERS_H + +namespace clang { + /// \brief Specifies the width of a type, e.g., short, long, or long long. + enum TypeSpecifierWidth { + TSW_unspecified, + TSW_short, + TSW_long, + TSW_longlong + }; + + /// \brief Specifies the signedness of a type, e.g., signed or unsigned. + enum TypeSpecifierSign { + TSS_unspecified, + TSS_signed, + TSS_unsigned + }; + + /// \brief Specifies the kind of type. + enum TypeSpecifierType { + TST_unspecified, + TST_void, + TST_char, + TST_wchar, // C++ wchar_t + TST_char16, // C++0x char16_t + TST_char32, // C++0x char32_t + TST_int, + TST_float, + TST_double, + TST_bool, // _Bool + TST_decimal32, // _Decimal32 + TST_decimal64, // _Decimal64 + TST_decimal128, // _Decimal128 + TST_enum, + TST_union, + TST_struct, + TST_class, // C++ class type + TST_typename, // Typedef, C++ class-name or enum name, etc. + TST_typeofType, + TST_typeofExpr, + TST_decltype, // C++0x decltype + TST_auto, // C++0x auto + TST_error // erroneous type + }; + + /// WrittenBuiltinSpecs - Structure that packs information about the + /// type specifiers that were written in a particular type specifier + /// sequence. + struct WrittenBuiltinSpecs { + /*DeclSpec::TST*/ unsigned Type : 5; + /*DeclSpec::TSS*/ unsigned Sign : 2; + /*DeclSpec::TSW*/ unsigned Width : 2; + bool ModeAttr : 1; + }; + + /// AccessSpecifier - A C++ access specifier (public, private, + /// protected), plus the special value "none" which means + /// different things in different contexts. + enum AccessSpecifier { + AS_public, + AS_protected, + AS_private, + AS_none + }; + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h new file mode 100644 index 0000000..f1edd1d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h @@ -0,0 +1,50 @@ +//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H +#define LLVM_CLANG_BASIC_TARGET_BUILTINS_H + +#include "clang/Basic/Builtins.h" +#undef PPC + +namespace clang { + + /// ARM builtins + namespace ARM { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsARM.def" + LastTSBuiltin + }; + } + + /// PPC builtins + namespace PPC { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsPPC.def" + LastTSBuiltin + }; + } + + /// X86 builtins + namespace X86 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsX86.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 new file mode 100644 index 0000000..00fd9b9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h @@ -0,0 +1,474 @@ +//===--- TargetInfo.h - Expose information about the target -----*- 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 TargetInfo interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_TARGETINFO_H +#define LLVM_CLANG_BASIC_TARGETINFO_H + +// FIXME: Daniel isn't smart enough to use a prototype for this. +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Triple.h" +#include "llvm/System/DataTypes.h" +#include <cassert> +#include <vector> +#include <string> + +namespace llvm { +struct fltSemantics; +class StringRef; +} + +namespace clang { +class Diagnostic; +class LangOptions; +class MacroBuilder; +class SourceLocation; +class SourceManager; +class TargetOptions; + +namespace Builtin { struct Info; } + +/// TargetInfo - This class exposes information about the current target. +/// +class 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 TLSSupported; + bool NoAsmVariants; // True if {|} are normal characters. + unsigned char PointerWidth, PointerAlign; + unsigned char IntWidth, IntAlign; + unsigned char FloatWidth, FloatAlign; + unsigned char DoubleWidth, DoubleAlign; + unsigned char LongDoubleWidth, LongDoubleAlign; + unsigned char LongWidth, LongAlign; + unsigned char LongLongWidth, LongLongAlign; + const char *DescriptionString; + const char *UserLabelPrefix; + const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; + unsigned char RegParmMax, SSERegParmMax; + + unsigned HasAlignMac68kSupport : 1; + + // TargetInfo Constructor. Default initializes all fields. + TargetInfo(const std::string &T); + +public: + /// CreateTargetInfo - Construct a target for the given options. + /// + /// \param Opts - The options to use to initialize the target. The target may + /// modify the options to canonicalize the target feature information to match + /// what the backend expects. + static TargetInfo* CreateTargetInfo(Diagnostic &Diags, TargetOptions &Opts); + + virtual ~TargetInfo(); + + ///===---- Target Data Type Query Methods -------------------------------===// + enum IntType { + NoInt = 0, + SignedShort, + UnsignedShort, + SignedInt, + UnsignedInt, + SignedLong, + UnsignedLong, + SignedLongLong, + UnsignedLongLong + }; +protected: + IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, + WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; + + /// Control whether the alignment of bit-field types is respected when laying + /// out structures. If true, then the alignment of the bit-field type will be + /// used to (a) impact the alignment of the containing structure, and (b) + /// ensure that the individual bit-field will not straddle an alignment + /// boundary. + unsigned UseBitFieldTypeAlignment : 1; + +public: + IntType getSizeType() const { return SizeType; } + IntType getIntMaxType() const { return IntMaxType; } + IntType getUIntMaxType() const { return UIntMaxType; } + IntType getPtrDiffType(unsigned AddrSpace) const { + return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace); + } + IntType getIntPtrType() const { return IntPtrType; } + IntType getWCharType() const { return WCharType; } + IntType getWIntType() const { return WIntType; } + IntType getChar16Type() const { return Char16Type; } + IntType getChar32Type() const { return Char32Type; } + IntType getInt64Type() const { return Int64Type; } + IntType getSigAtomicType() const { return SigAtomicType; } + + + /// getTypeWidth - Return the width (in bits) of the specified integer type + /// enum. For example, SignedInt -> getIntWidth(). + unsigned getTypeWidth(IntType T) const; + + /// getTypeAlign - Return the alignment (in bits) of the specified integer + /// type enum. For example, SignedInt -> getIntAlign(). + unsigned getTypeAlign(IntType T) const; + + /// isTypeSigned - Return whether an integer types is signed. Returns true if + /// the type is signed; false otherwise. + bool isTypeSigned(IntType T) const; + + /// getPointerWidth - Return the width of pointers on this target, for the + /// specified address space. + uint64_t getPointerWidth(unsigned AddrSpace) const { + return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace); + } + uint64_t getPointerAlign(unsigned AddrSpace) const { + return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace); + } + + /// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this + /// target, in bits. + unsigned getBoolWidth(bool isWide = false) const { return 8; } // FIXME + unsigned getBoolAlign(bool isWide = false) const { return 8; } // FIXME + + unsigned getCharWidth() const { return 8; } // FIXME + unsigned getCharAlign() const { return 8; } // FIXME + + /// getShortWidth/Align - Return the size of 'signed short' and + /// 'unsigned short' for this target, in bits. + unsigned getShortWidth() const { return 16; } // FIXME + unsigned getShortAlign() const { return 16; } // FIXME + + /// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for + /// this target, in bits. + unsigned getIntWidth() const { return IntWidth; } + unsigned getIntAlign() const { return IntAlign; } + + /// getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' + /// for this target, in bits. + unsigned getLongWidth() const { return LongWidth; } + unsigned getLongAlign() const { return LongAlign; } + + /// getLongLongWidth/Align - Return the size of 'signed long long' and + /// 'unsigned long long' for this target, in bits. + unsigned getLongLongWidth() const { return LongLongWidth; } + unsigned getLongLongAlign() const { return LongLongAlign; } + + /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in + /// bits. + unsigned getWCharWidth() const { return getTypeWidth(WCharType); } + unsigned getWCharAlign() const { return getTypeAlign(WCharType); } + + /// getChar16Width/Align - Return the size of 'char16_t' for this target, in + /// bits. + unsigned getChar16Width() const { return getTypeWidth(Char16Type); } + unsigned getChar16Align() const { return getTypeAlign(Char16Type); } + + /// getChar32Width/Align - Return the size of 'char32_t' for this target, in + /// bits. + unsigned getChar32Width() const { return getTypeWidth(Char32Type); } + unsigned getChar32Align() const { return getTypeAlign(Char32Type); } + + /// getFloatWidth/Align/Format - Return the size/align/format of 'float'. + unsigned getFloatWidth() const { return FloatWidth; } + unsigned getFloatAlign() const { return FloatAlign; } + const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; } + + /// getDoubleWidth/Align/Format - Return the size/align/format of 'double'. + unsigned getDoubleWidth() const { return DoubleWidth; } + unsigned getDoubleAlign() const { return DoubleAlign; } + const llvm::fltSemantics &getDoubleFormat() const { return *DoubleFormat; } + + /// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long + /// double'. + unsigned getLongDoubleWidth() const { return LongDoubleWidth; } + unsigned getLongDoubleAlign() const { return LongDoubleAlign; } + const llvm::fltSemantics &getLongDoubleFormat() const { + return *LongDoubleFormat; + } + + /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this + /// target, in bits. + unsigned getIntMaxTWidth() const { + return getTypeWidth(IntMaxType); + } + + /// getUserLabelPrefix - This returns the default value of the + /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by + /// default. On most platforms this is "_", but it is "" on some, and "." on + /// others. + const char *getUserLabelPrefix() const { + return UserLabelPrefix; + } + + bool useBitFieldTypeAlignment() const { + return UseBitFieldTypeAlignment; + } + + /// hasAlignMac68kSupport - Check whether this target support '#pragma options + /// align=mac68k'. + bool hasAlignMac68kSupport() const { + return HasAlignMac68kSupport; + } + + /// getTypeName - Return the user string for the specified integer type enum. + /// For example, SignedShort -> "short". + static const char *getTypeName(IntType T); + + /// getTypeConstantSuffix - Return the constant suffix for the specified + /// integer type enum. For example, SignedLong -> "L". + static const char *getTypeConstantSuffix(IntType T); + + ///===---- Other target property query methods --------------------------===// + + /// getTargetDefines - Appends the target-specific #define values for this + /// target set to the specified buffer. + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const = 0; + + + /// getTargetBuiltins - Return information about target-specific builtins for + /// the current primary target, and info about which builtins are non-portable + /// across the current set of primary and secondary targets. + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const = 0; + + /// getVAListDeclaration - Return the declaration to use for + /// __builtin_va_list, which is target-specific. + virtual const char *getVAListDeclaration() const = 0; + + /// isValidGCCRegisterName - Returns whether the passed in string + /// is a valid register name according to GCC. This is used by Sema for + /// inline asm statements. + bool isValidGCCRegisterName(llvm::StringRef Name) const; + + // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name. + // For example, on x86 it will return "ax" when "eax" is passed in. + llvm::StringRef getNormalizedGCCRegisterName(llvm::StringRef Name) const; + + struct ConstraintInfo { + enum { + CI_None = 0x00, + CI_AllowsMemory = 0x01, + CI_AllowsRegister = 0x02, + CI_ReadWrite = 0x04, // "+r" output constraint (read and write). + CI_HasMatchingInput = 0x08 // This output operand has a matching input. + }; + unsigned Flags; + int TiedOperand; + + std::string ConstraintStr; // constraint: "=rm" + std::string Name; // Operand name: [foo] with no []'s. + public: + ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name) + : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), + Name(Name.str()) {} + + const std::string &getConstraintStr() const { return ConstraintStr; } + const std::string &getName() const { return Name; } + bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; } + bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } + bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } + + /// hasMatchingInput - Return true if this output operand has a matching + /// (tied) input operand. + bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; } + + /// hasTiedOperand() - Return true if this input operand is a matching + /// constraint that ties it to an output operand. If this returns true, + /// then getTiedOperand will indicate which output operand this is tied to. + bool hasTiedOperand() const { return TiedOperand != -1; } + unsigned getTiedOperand() const { + assert(hasTiedOperand() && "Has no tied operand!"); + return (unsigned)TiedOperand; + } + + void setIsReadWrite() { Flags |= CI_ReadWrite; } + void setAllowsMemory() { Flags |= CI_AllowsMemory; } + void setAllowsRegister() { Flags |= CI_AllowsRegister; } + void setHasMatchingInput() { Flags |= CI_HasMatchingInput; } + + /// setTiedOperand - Indicate that this is an input operand that is tied to + /// the specified output operand. Copy over the various constraint + /// information from the output. + void setTiedOperand(unsigned N, ConstraintInfo &Output) { + Output.setHasMatchingInput(); + Flags = Output.Flags; + TiedOperand = N; + // Don't copy Name or constraint string. + } + }; + + // validateOutputConstraint, validateInputConstraint - Checks that + // a constraint is valid and provides information about it. + // FIXME: These should return a real error instead of just true/false. + bool validateOutputConstraint(ConstraintInfo &Info) const; + bool validateInputConstraint(ConstraintInfo *OutputConstraints, + unsigned NumOutputs, + ConstraintInfo &info) const; + bool resolveSymbolicName(const char *&Name, + ConstraintInfo *OutputConstraints, + unsigned NumOutputs, unsigned &Index) const; + + virtual std::string convertConstraint(const char Constraint) const { + return std::string(1, Constraint); + } + + // Returns a string of target-specific clobbers, in LLVM format. + virtual const char *getClobbers() const = 0; + + + /// getTriple - Return the target triple of the primary target. + const llvm::Triple &getTriple() const { + return Triple; + } + + const char *getTargetDescription() const { + return DescriptionString; + } + + struct GCCRegAlias { + const char * const Aliases[5]; + const char * const Register; + }; + + virtual bool useGlobalsForAutomaticVariables() const { return false; } + + /// getCFStringSection - Return the section to use for CFString + /// literals, or 0 if no special section is used. + virtual const char *getCFStringSection() const { + return "__DATA,__cfstring"; + } + + /// getNSStringSection - Return the section to use for NSString + /// literals, or 0 if no special section is used. + virtual const char *getNSStringSection() const { + return "__OBJC,__cstring_object,regular,no_dead_strip"; + } + + /// getNSStringNonFragileABISection - Return the section to use for + /// NSString literals, or 0 if no special section is used (NonFragile ABI). + virtual const char *getNSStringNonFragileABISection() const { + return "__DATA, __objc_stringobj, regular, no_dead_strip"; + } + + /// isValidSectionSpecifier - This is an optional hook that targets can + /// implement to perform semantic checking on attribute((section("foo"))) + /// specifiers. In this case, "foo" is passed in to be checked. If the + /// section specifier is invalid, the backend should return a non-empty string + /// that indicates the problem. + /// + /// This hook is a simple quality of implementation feature to catch errors + /// and give good diagnostics in cases when the assembler or code generator + /// would otherwise reject the section specifier. + /// + virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const { + return ""; + } + + /// setForcedLangOptions - Set forced language options. + /// Apply changes to the target information with respect to certain + /// language options which change the target configuration. + virtual void setForcedLangOptions(LangOptions &Opts); + + /// getDefaultFeatures - Get the default set of target features for + /// the \args CPU; this should include all legal feature strings on + /// the target. + virtual void getDefaultFeatures(const std::string &CPU, + llvm::StringMap<bool> &Features) const { + } + + /// getABI - Get the ABI in use. + virtual const char *getABI() const { + return ""; + } + + /// setCPU - Target the specific CPU. + /// + /// \return - False on error (invalid CPU name). + // + // FIXME: Remove this. + virtual bool setCPU(const std::string &Name) { + return true; + } + + /// setABI - Use the specific ABI. + /// + /// \return - False on error (invalid ABI name). + virtual bool setABI(const std::string &Name) { + return false; + } + + /// setFeatureEnabled - Enable or disable a specific target feature, + /// the feature name must be valid. + /// + /// \return - False on error (invalid feature name). + virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, + const std::string &Name, + bool Enabled) const { + return false; + } + + /// HandleTargetOptions - Perform initialization based on the user configured + /// set of features (e.g., +sse4). The list is guaranteed to have at most one + /// entry per feature. + /// + /// The target may modify the features list, to change which options are + /// passed onwards to the backend. + virtual void HandleTargetFeatures(std::vector<std::string> &Features) { + } + + // getRegParmMax - Returns maximal number of args passed in registers. + unsigned getRegParmMax() const { + return RegParmMax; + } + + /// isTLSSupported - Whether the target supports thread-local storage. + bool isTLSSupported() const { + return TLSSupported; + } + + /// hasNoAsmVariants - Return true if {|} are normal characters in the + /// asm string. If this returns false (the default), then {abc|xyz} is syntax + /// that says that when compiling for asm variant #0, "abc" should be + /// generated, but when compiling for asm variant #1, "xyz" should be + /// generated. + bool hasNoAsmVariants() const { + return NoAsmVariants; + } + + /// getEHDataRegisterNumber - Return the register number that + /// __builtin_eh_return_regno would return with the specified argument. + virtual int getEHDataRegisterNumber(unsigned RegNo) const { + return -1; + } + + +protected: + virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { + return PointerWidth; + } + virtual uint64_t getPointerAlignV(unsigned AddrSpace) const { + return PointerAlign; + } + virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const { + return PtrDiffType; + } + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const = 0; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const = 0; + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const= 0; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h new file mode 100644 index 0000000..eeaab15 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h @@ -0,0 +1,39 @@ +//===--- TargetOptions.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H +#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// TargetOptions - Options for controlling the target. +class TargetOptions { +public: + + /// If given, the name of the target triple to compile for. If not given the + /// target will be selected to match the host. + std::string Triple; + + /// If given, the name of the target CPU to generate code for. + std::string CPU; + + /// If given, the name of the target ABI to use. + std::string ABI; + + /// The list of target specific features to enable or disable -- this should + /// be a list of strings starting with by '+' or '-'. + std::vector<std::string> Features; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h new file mode 100644 index 0000000..c6ea05b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h @@ -0,0 +1,39 @@ +//===--- TemplateKinds.h - Enum values for C++ Template Kinds ---*- 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 TemplateNameKind enum. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_TEMPLATEKINDS_H +#define LLVM_CLANG_TEMPLATEKINDS_H + +namespace clang { + +/// \brief Specifies the kind of template name that an identifier refers to. +enum TemplateNameKind { + /// The name does not refer to a template. + TNK_Non_template = 0, + /// The name refers to a function template or a set of overloaded + /// functions that includes at least one function template. + TNK_Function_template, + /// The name refers to a template whose specialization produces a + /// type. The template itself could be a class template, template + /// template parameter, or C++0x template alias. + TNK_Type_template, + /// The name refers to a dependent template name. Whether the + /// template name is assumed to refer to a type template or a + /// function template depends on the context in which the template + /// name occurs. + TNK_Dependent_template_name +}; + +} +#endif + + diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def new file mode 100644 index 0000000..b16b828 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def @@ -0,0 +1,429 @@ +//===--- TokenKinds.def - C Family Token Kind 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 TokenKind database. This includes normal tokens like +// tok::ampamp (corresponding to the && token) as well as keywords for various +// languages. Users of this file must optionally #define the TOK, KEYWORD, +// ALIAS, or PPKEYWORD macros to make use of this file. +// +//===----------------------------------------------------------------------===// + +#ifndef TOK +#define TOK(X) +#endif +#ifndef PUNCTUATOR +#define PUNCTUATOR(X,Y) TOK(X) +#endif +#ifndef KEYWORD +#define KEYWORD(X,Y) TOK(kw_ ## X) +#endif +#ifndef ALIAS +#define ALIAS(X,Y,Z) +#endif +#ifndef PPKEYWORD +#define PPKEYWORD(X) +#endif +#ifndef CXX_KEYWORD_OPERATOR +#define CXX_KEYWORD_OPERATOR(X,Y) +#endif +#ifndef OBJC1_AT_KEYWORD +#define OBJC1_AT_KEYWORD(X) +#endif +#ifndef OBJC2_AT_KEYWORD +#define OBJC2_AT_KEYWORD(X) +#endif +#ifndef ANNOTATION +#define ANNOTATION(X) TOK(annot_ ## X) +#endif + +//===----------------------------------------------------------------------===// +// Preprocessor keywords. +//===----------------------------------------------------------------------===// + +// These have meaning after a '#' at the start of a line. These define enums in +// the tok::pp_* namespace. Note that IdentifierInfo::getPPKeywordID must be +// manually updated if something is added here. +PPKEYWORD(not_keyword) + +// C99 6.10.1 - Conditional Inclusion. +PPKEYWORD(if) +PPKEYWORD(ifdef) +PPKEYWORD(ifndef) +PPKEYWORD(elif) +PPKEYWORD(else) +PPKEYWORD(endif) +PPKEYWORD(defined) + +// C99 6.10.2 - Source File Inclusion. +PPKEYWORD(include) +PPKEYWORD(__include_macros) + +// C99 6.10.3 - Macro Replacement. +PPKEYWORD(define) +PPKEYWORD(undef) + +// C99 6.10.4 - Line Control. +PPKEYWORD(line) + +// C99 6.10.5 - Error Directive. +PPKEYWORD(error) + +// C99 6.10.6 - Pragma Directive. +PPKEYWORD(pragma) + +// GNU Extensions. +PPKEYWORD(import) +PPKEYWORD(include_next) +PPKEYWORD(warning) +PPKEYWORD(ident) +PPKEYWORD(sccs) +PPKEYWORD(assert) +PPKEYWORD(unassert) + +//===----------------------------------------------------------------------===// +// Language keywords. +//===----------------------------------------------------------------------===// + +// These define members of the tok::* namespace. + +TOK(unknown) // Not a token. +TOK(eof) // End of file. +TOK(eom) // End of macro (end of line inside a macro). +TOK(code_completion) // Code completion marker + +// C99 6.4.9: Comments. +TOK(comment) // Comment (only in -E -C[C] mode) + +// C99 6.4.2: Identifiers. +TOK(identifier) // abcde123 + +// C99 6.4.4.1: Integer Constants +// C99 6.4.4.2: Floating Constants +TOK(numeric_constant) // 0x123 + +// C99 6.4.4: Character Constants +TOK(char_constant) // 'a' L'b' + +// C99 6.4.5: String Literals. +TOK(string_literal) // "foo" +TOK(wide_string_literal) // L"foo" +TOK(angle_string_literal)// <foo> + +// C99 6.4.6: Punctuators. +PUNCTUATOR(l_square, "[") +PUNCTUATOR(r_square, "]") +PUNCTUATOR(l_paren, "(") +PUNCTUATOR(r_paren, ")") +PUNCTUATOR(l_brace, "{") +PUNCTUATOR(r_brace, "}") +PUNCTUATOR(period, ".") +PUNCTUATOR(ellipsis, "...") +PUNCTUATOR(amp, "&") +PUNCTUATOR(ampamp, "&&") +PUNCTUATOR(ampequal, "&=") +PUNCTUATOR(star, "*") +PUNCTUATOR(starequal, "*=") +PUNCTUATOR(plus, "+") +PUNCTUATOR(plusplus, "++") +PUNCTUATOR(plusequal, "+=") +PUNCTUATOR(minus, "-") +PUNCTUATOR(arrow, "->") +PUNCTUATOR(minusminus, "--") +PUNCTUATOR(minusequal, "-=") +PUNCTUATOR(tilde, "~") +PUNCTUATOR(exclaim, "!") +PUNCTUATOR(exclaimequal, "!=") +PUNCTUATOR(slash, "/") +PUNCTUATOR(slashequal, "/=") +PUNCTUATOR(percent, "%") +PUNCTUATOR(percentequal, "%=") +PUNCTUATOR(less, "<") +PUNCTUATOR(lessless, "<<") +PUNCTUATOR(lessequal, "<=") +PUNCTUATOR(lesslessequal, "<<=") +PUNCTUATOR(greater, ">") +PUNCTUATOR(greatergreater, ">>") +PUNCTUATOR(greaterequal, ">=") +PUNCTUATOR(greatergreaterequal, ">>=") +PUNCTUATOR(caret, "^") +PUNCTUATOR(caretequal, "^=") +PUNCTUATOR(pipe, "|") +PUNCTUATOR(pipepipe, "||") +PUNCTUATOR(pipeequal, "|=") +PUNCTUATOR(question, "?") +PUNCTUATOR(colon, ":") +PUNCTUATOR(semi, ";") +PUNCTUATOR(equal, "=") +PUNCTUATOR(equalequal, "==") +PUNCTUATOR(comma, ",") +PUNCTUATOR(hash, "#") +PUNCTUATOR(hashhash, "##") +PUNCTUATOR(hashat, "#@") + +// C++ Support +PUNCTUATOR(periodstar, ".*") +PUNCTUATOR(arrowstar, "->*") +PUNCTUATOR(coloncolon, "::") + +// Objective C support. +PUNCTUATOR(at, "@") + +// C99 6.4.1: Keywords. These turn into kw_* tokens. +// Flags allowed: +// KEYALL - This is a keyword in all variants of C and C++, or it +// 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 +// KEYCXX - This is a C++ keyword, or a C++-specific keyword in the +// implementation namespace +// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x +// KEYGNU - This is a keyword if GNU extensions are enabled +// KEYMS - This is a keyword if Microsoft extensions are enabled +// +KEYWORD(auto , KEYALL) +KEYWORD(break , KEYALL) +KEYWORD(case , KEYALL) +KEYWORD(char , KEYALL) +KEYWORD(const , KEYALL) +KEYWORD(continue , KEYALL) +KEYWORD(default , KEYALL) +KEYWORD(do , KEYALL) +KEYWORD(double , KEYALL) +KEYWORD(else , KEYALL) +KEYWORD(enum , KEYALL) +KEYWORD(extern , KEYALL) +KEYWORD(float , KEYALL) +KEYWORD(for , KEYALL) +KEYWORD(goto , KEYALL) +KEYWORD(if , KEYALL) +KEYWORD(inline , KEYC99|KEYCXX|KEYGNU) +KEYWORD(int , KEYALL) +KEYWORD(long , KEYALL) +KEYWORD(register , KEYALL) +KEYWORD(restrict , KEYC99) +KEYWORD(return , KEYALL) +KEYWORD(short , KEYALL) +KEYWORD(signed , KEYALL) +KEYWORD(sizeof , KEYALL) +KEYWORD(static , KEYALL) +KEYWORD(struct , KEYALL) +KEYWORD(switch , KEYALL) +KEYWORD(typedef , KEYALL) +KEYWORD(union , KEYALL) +KEYWORD(unsigned , KEYALL) +KEYWORD(void , KEYALL) +KEYWORD(volatile , KEYALL) +KEYWORD(while , KEYALL) +KEYWORD(_Bool , KEYNOMS) +KEYWORD(_Complex , KEYALL) +KEYWORD(_Imaginary , KEYALL) +KEYWORD(__func__ , KEYALL) + +// C++ 2.11p1: Keywords. +KEYWORD(asm , KEYCXX|KEYGNU) +KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC) +KEYWORD(catch , KEYCXX) +KEYWORD(class , KEYCXX) +KEYWORD(const_cast , KEYCXX) +KEYWORD(delete , KEYCXX) +KEYWORD(dynamic_cast , KEYCXX) +KEYWORD(explicit , KEYCXX) +KEYWORD(export , KEYCXX) +KEYWORD(false , BOOLSUPPORT|KEYALTIVEC) +KEYWORD(friend , KEYCXX) +KEYWORD(mutable , KEYCXX) +KEYWORD(namespace , KEYCXX) +KEYWORD(new , KEYCXX) +KEYWORD(operator , KEYCXX) +KEYWORD(private , KEYCXX) +KEYWORD(protected , KEYCXX) +KEYWORD(public , KEYCXX) +KEYWORD(reinterpret_cast , KEYCXX) +KEYWORD(static_cast , KEYCXX) +KEYWORD(template , KEYCXX) +KEYWORD(this , KEYCXX) +KEYWORD(throw , KEYCXX) +KEYWORD(true , BOOLSUPPORT|KEYALTIVEC) +KEYWORD(try , KEYCXX) +KEYWORD(typename , KEYCXX) +KEYWORD(typeid , KEYCXX) +KEYWORD(using , KEYCXX) +KEYWORD(virtual , KEYCXX) +KEYWORD(wchar_t , KEYCXX) + +// C++ 2.5p2: Alternative Representations. +CXX_KEYWORD_OPERATOR(and , ampamp) +CXX_KEYWORD_OPERATOR(and_eq , ampequal) +CXX_KEYWORD_OPERATOR(bitand , amp) +CXX_KEYWORD_OPERATOR(bitor , pipe) +CXX_KEYWORD_OPERATOR(compl , tilde) +CXX_KEYWORD_OPERATOR(not , exclaim) +CXX_KEYWORD_OPERATOR(not_eq , exclaimequal) +CXX_KEYWORD_OPERATOR(or , pipepipe) +CXX_KEYWORD_OPERATOR(or_eq , pipeequal) +CXX_KEYWORD_OPERATOR(xor , caret) +CXX_KEYWORD_OPERATOR(xor_eq , caretequal) + +// C++0x keywords +KEYWORD(alignof , KEYCXX0X) +KEYWORD(axiom , KEYCXX0X) +KEYWORD(char16_t , KEYCXX0X) +KEYWORD(char32_t , KEYCXX0X) +KEYWORD(concept , KEYCXX0X) +KEYWORD(concept_map , KEYCXX0X) +KEYWORD(constexpr , KEYCXX0X) +KEYWORD(decltype , KEYCXX0X) +KEYWORD(late_check , KEYCXX0X) +KEYWORD(nullptr , KEYCXX0X) +KEYWORD(requires , KEYCXX0X) +KEYWORD(static_assert , KEYCXX0X) +KEYWORD(thread_local , KEYCXX0X) + +// GNU Extensions (in impl-reserved namespace) +KEYWORD(_Decimal32 , KEYALL) +KEYWORD(_Decimal64 , KEYALL) +KEYWORD(_Decimal128 , KEYALL) +KEYWORD(__null , KEYCXX) +KEYWORD(__alignof , KEYALL) +KEYWORD(__attribute , KEYALL) +KEYWORD(__builtin_choose_expr , KEYALL) +KEYWORD(__builtin_offsetof , KEYALL) +KEYWORD(__builtin_types_compatible_p, KEYALL) +KEYWORD(__builtin_va_arg , KEYALL) +KEYWORD(__extension__ , KEYALL) +KEYWORD(__imag , KEYALL) +KEYWORD(__label__ , KEYALL) +KEYWORD(__real , KEYALL) +KEYWORD(__thread , KEYALL) +KEYWORD(__FUNCTION__ , KEYALL) +KEYWORD(__PRETTY_FUNCTION__ , KEYALL) + +// GNU Extensions (outside impl-reserved namespace) +KEYWORD(typeof , KEYGNU) + +// GNU and MS Type Traits +KEYWORD(__has_nothrow_assign , KEYCXX) +KEYWORD(__has_nothrow_copy , KEYCXX) +KEYWORD(__has_nothrow_constructor , KEYCXX) +KEYWORD(__has_trivial_assign , KEYCXX) +KEYWORD(__has_trivial_copy , KEYCXX) +KEYWORD(__has_trivial_constructor , KEYCXX) +KEYWORD(__has_trivial_destructor , KEYCXX) +KEYWORD(__has_virtual_destructor , KEYCXX) +KEYWORD(__is_abstract , KEYCXX) +KEYWORD(__is_base_of , KEYCXX) +KEYWORD(__is_class , KEYCXX) +KEYWORD(__is_empty , KEYCXX) +KEYWORD(__is_enum , KEYCXX) +KEYWORD(__is_pod , KEYCXX) +KEYWORD(__is_polymorphic , KEYCXX) +KEYWORD(__is_union , KEYCXX) +// Tentative name - there's no implementation of std::is_literal_type yet. +KEYWORD(__is_literal , KEYCXX) +// FIXME: Add MS's traits, too. + +// Apple Extension. +KEYWORD(__private_extern__ , KEYALL) + +// Microsoft Extension. +KEYWORD(__declspec , KEYALL) +KEYWORD(__cdecl , KEYALL) +KEYWORD(__stdcall , KEYALL) +KEYWORD(__fastcall , KEYALL) +KEYWORD(__thiscall , KEYALL) +KEYWORD(__forceinline , KEYALL) + +// Altivec Extension. +KEYWORD(__vector , KEYALTIVEC) +KEYWORD(__pixel , KEYALTIVEC) + +// Alternate spelling for various tokens. There are GCC extensions in all +// languages, but should not be disabled in strict conformance mode. +ALIAS("__attribute__", __attribute, KEYALL) +ALIAS("__const" , const , KEYALL) +ALIAS("__const__" , const , KEYALL) +ALIAS("__alignof__" , __alignof , KEYALL) +ALIAS("__asm" , asm , KEYALL) +ALIAS("__asm__" , asm , KEYALL) +ALIAS("__complex" , _Complex , KEYALL) +ALIAS("__complex__" , _Complex , KEYALL) +ALIAS("__imag__" , __imag , KEYALL) +ALIAS("__inline" , inline , KEYALL) +ALIAS("__inline__" , inline , KEYALL) +ALIAS("__real__" , __real , KEYALL) +ALIAS("__restrict" , restrict , KEYALL) +ALIAS("__restrict__" , restrict , KEYALL) +ALIAS("__signed" , signed , KEYALL) +ALIAS("__signed__" , signed , KEYALL) +ALIAS("__typeof" , typeof , KEYALL) +ALIAS("__typeof__" , typeof , KEYALL) +ALIAS("__volatile" , volatile , KEYALL) +ALIAS("__volatile__" , volatile , KEYALL) + +// Microsoft extensions which should be disabled in strict conformance mode +KEYWORD(__ptr64 , KEYMS) +KEYWORD(__w64 , KEYMS) +ALIAS("_asm" , asm , KEYMS) +ALIAS("_cdecl" , __cdecl , KEYMS) +ALIAS("_fastcall" , __fastcall , KEYMS) +ALIAS("_stdcall" , __stdcall , KEYMS) +ALIAS("_thiscall" , __thiscall , KEYMS) + +//===----------------------------------------------------------------------===// +// Objective-C @-preceeded keywords. +//===----------------------------------------------------------------------===// + +// These have meaning after an '@' in Objective-C mode. These define enums in +// the tok::objc_* namespace. + +OBJC1_AT_KEYWORD(not_keyword) +OBJC1_AT_KEYWORD(class) +OBJC1_AT_KEYWORD(compatibility_alias) +OBJC1_AT_KEYWORD(defs) +OBJC1_AT_KEYWORD(encode) +OBJC1_AT_KEYWORD(end) +OBJC1_AT_KEYWORD(implementation) +OBJC1_AT_KEYWORD(interface) +OBJC1_AT_KEYWORD(private) +OBJC1_AT_KEYWORD(protected) +OBJC1_AT_KEYWORD(protocol) +OBJC1_AT_KEYWORD(public) +OBJC1_AT_KEYWORD(selector) +OBJC1_AT_KEYWORD(throw) +OBJC1_AT_KEYWORD(try) +OBJC1_AT_KEYWORD(catch) +OBJC1_AT_KEYWORD(finally) +OBJC1_AT_KEYWORD(synchronized) + +OBJC2_AT_KEYWORD(property) +OBJC2_AT_KEYWORD(package) +OBJC2_AT_KEYWORD(required) +OBJC2_AT_KEYWORD(optional) +OBJC2_AT_KEYWORD(synthesize) +OBJC2_AT_KEYWORD(dynamic) + +// TODO: What to do about context-sensitive keywords like: +// bycopy/byref/in/inout/oneway/out? + +ANNOTATION(cxxscope) // annotation for a C++ scope spec, e.g. "::foo::bar::" +ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly + // qualified) typename, e.g. "foo::MyClass", or + // template-id that names a type ("std::vector<int>") +ANNOTATION(template_id) // annotation for a C++ template-id that names a + // function template specialization (not a type), + // e.g., "std::swap<int>" +#undef ANNOTATION +#undef OBJC2_AT_KEYWORD +#undef OBJC1_AT_KEYWORD +#undef CXX_KEYWORD_OPERATOR +#undef PPKEYWORD +#undef ALIAS +#undef KEYWORD +#undef PUNCTUATOR +#undef TOK diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h new file mode 100644 index 0000000..85dc067 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h @@ -0,0 +1,64 @@ +//===--- TokenKinds.h - Enum values for C Token Kinds -----------*- 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 TokenKind enum and support functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOKENKINDS_H +#define LLVM_CLANG_TOKENKINDS_H + +namespace clang { + +namespace tok { + +/// TokenKind - This provides a simple uniform namespace for tokens from all C +/// languages. +enum TokenKind { +#define TOK(X) X, +#include "clang/Basic/TokenKinds.def" + NUM_TOKENS +}; + +/// PPKeywordKind - This provides a namespace for preprocessor keywords which +/// start with a '#' at the beginning of the line. +enum PPKeywordKind { +#define PPKEYWORD(X) pp_##X, +#include "clang/Basic/TokenKinds.def" + NUM_PP_KEYWORDS +}; + +/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which +/// start with an '@'. +enum ObjCKeywordKind { +#define OBJC1_AT_KEYWORD(X) objc_##X, +#define OBJC2_AT_KEYWORD(X) objc_##X, +#include "clang/Basic/TokenKinds.def" + NUM_OBJC_KEYWORDS +}; + +/// \brief Determines the name of a token as used within the front end. +/// +/// The name of a token will be an internal name (such as "l_square") +/// and should not be used as part of diagnostic messages. +const char *getTokenName(enum TokenKind Kind); + +/// \brief Determines the spelling of simple punctuation tokens like +/// '!' or '%', and returns NULL for literal and annotation tokens. +/// +/// This routine only retrieves the "simple" spelling of the token, +/// and will not produce any alternative spellings (e.g., a +/// digraph). For the actual spelling of a given Token, use +/// Preprocessor::getSpelling(). +const char *getTokenSimpleSpelling(enum TokenKind Kind); + +} // end namespace tok +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h new file mode 100644 index 0000000..36b8300 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h @@ -0,0 +1,41 @@ +//===--- TypeTraits.h - C++ Type Traits Support Enumerations ----*- 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 enumerations for the type traits support. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TYPETRAITS_H +#define LLVM_CLANG_TYPETRAITS_H + +namespace clang { + + /// UnaryTypeTrait - Names for the unary type traits. + enum UnaryTypeTrait { + UTT_HasNothrowAssign, + UTT_HasNothrowCopy, + UTT_HasNothrowConstructor, + UTT_HasTrivialAssign, + UTT_HasTrivialCopy, + UTT_HasTrivialConstructor, + UTT_HasTrivialDestructor, + UTT_HasVirtualDestructor, + UTT_IsAbstract, + UTT_IsClass, + UTT_IsEmpty, + UTT_IsEnum, + UTT_IsPOD, + UTT_IsPolymorphic, + UTT_IsUnion, + UTT_IsLiteral + }; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h new file mode 100644 index 0000000..b3b6184 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h @@ -0,0 +1,71 @@ +//===- Version.h - Clang Version Number -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines version macros and version-related utility functions +// for Clang. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_VERSION_H +#define LLVM_CLANG_BASIC_VERSION_H + +#include "llvm/ADT/StringRef.h" + +/// \brief Clang major version +#define CLANG_VERSION_MAJOR 2 + +// FIXME: Updates to this file must also update CMakeLists.txt and VER. +/// \brief Clang minor version +#define CLANG_VERSION_MINOR 0 + +/// \brief Clang patchlevel version +// #define CLANG_VERSION_PATCHLEVEL 1 + +/// \brief Helper macro for CLANG_VERSION_STRING. +#define CLANG_MAKE_VERSION_STRING2(X) #X + +#ifdef CLANG_VERSION_PATCHLEVEL +/// \brief Helper macro for CLANG_VERSION_STRING. +#define CLANG_MAKE_VERSION_STRING(X,Y,Z) CLANG_MAKE_VERSION_STRING2(X.Y.Z) + +/// \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) +#else +/// \brief Helper macro for CLANG_VERSION_STRING. +#define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y) + +/// \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) +#endif + +namespace clang { + /// \brief Retrieves the repository path (e.g., Subversion path) that + /// identifies the particular Clang branch, tag, or trunk from which this + /// Clang was built. + llvm::StringRef getClangRepositoryPath(); + + /// \brief Retrieves the repository revision number (or identifer) from which + /// this Clang was built. + std::string getClangRevision(); + + /// \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, + /// and the vendor tag. + std::string getClangFullVersion(); +} + +#endif // LLVM_CLANG_BASIC_VERSION_H diff --git a/contrib/llvm/tools/clang/include/clang/CMakeLists.txt b/contrib/llvm/tools/clang/include/clang/CMakeLists.txt new file mode 100644 index 0000000..c288048 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(AST) +add_subdirectory(Basic) +add_subdirectory(Driver) diff --git a/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugReporter.h new file mode 100644 index 0000000..5b65d52 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugReporter.h @@ -0,0 +1,479 @@ +//===--- BugReporter.h - Generate PathDiagnostics --------------*- 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 BugReporter, a utility class for generating +// PathDiagnostics for analyses based on GRState. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER +#define LLVM_CLANG_ANALYSIS_BUGREPORTER + +#include "clang/Basic/SourceLocation.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/ImmutableSet.h" +#include "llvm/ADT/SmallSet.h" +#include <list> + +namespace clang { + +class PathDiagnostic; +class PathDiagnosticPiece; +class PathDiagnosticClient; +class ASTContext; +class Diagnostic; +class ExplodedNode; +class ExplodedGraph; +class BugReporter; +class BugReporterContext; +class GRExprEngine; +class GRState; +class Stmt; +class BugType; +class ParentMap; + +//===----------------------------------------------------------------------===// +// Interface for individual bug reports. +//===----------------------------------------------------------------------===// + +class BugReporterVisitor : public llvm::FoldingSetNode { +public: + virtual ~BugReporterVisitor(); + virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N, + const ExplodedNode* PrevN, + BugReporterContext& BRC) = 0; + + virtual bool isOwnedByReporterContext() { return true; } + virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; +}; + +// FIXME: Combine this with RangedBugReport and remove RangedBugReport. +class BugReport : public BugReporterVisitor { +protected: + BugType& BT; + std::string ShortDescription; + std::string Description; + const ExplodedNode *EndNode; + SourceRange R; + +protected: + friend class BugReporter; + friend class BugReportEquivClass; + + virtual void Profile(llvm::FoldingSetNodeID& hash) const { + hash.AddInteger(getLocation().getRawEncoding()); + } + +public: + class NodeResolver { + public: + virtual ~NodeResolver() {} + virtual const ExplodedNode* + getOriginalNode(const ExplodedNode* N) = 0; + }; + + BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n) + : BT(bt), Description(desc), EndNode(n) {} + + BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc, + const ExplodedNode *n) + : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {} + + virtual ~BugReport(); + + virtual bool isOwnedByReporterContext() { return false; } + + const BugType& getBugType() const { return BT; } + BugType& getBugType() { return BT; } + + // FIXME: Perhaps this should be moved into a subclass? + const ExplodedNode* getEndNode() const { return EndNode; } + + // FIXME: Do we need this? Maybe getLocation() should return a ProgramPoint + // object. + // FIXME: If we do need it, we can probably just make it private to + // BugReporter. + const Stmt* getStmt() const; + + const llvm::StringRef getDescription() const { return Description; } + + const llvm::StringRef getShortDescription() const { + return ShortDescription.empty() ? Description : ShortDescription; + } + + // FIXME: Is this needed? + virtual std::pair<const char**,const char**> getExtraDescriptiveText() { + return std::make_pair((const char**)0,(const char**)0); + } + + // FIXME: Perhaps move this into a subclass. + virtual PathDiagnosticPiece* getEndPath(BugReporterContext& BRC, + const ExplodedNode* N); + + /// getLocation - Return the "definitive" location of the reported bug. + /// While a bug can span an entire path, usually there is a specific + /// location that can be used to identify where the key issue occured. + /// This location is used by clients rendering diagnostics. + virtual SourceLocation getLocation() const; + + /// getRanges - Returns the source ranges associated with this bug. + virtual void getRanges(const SourceRange*& beg, const SourceRange*& end); + + virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N, + const ExplodedNode* PrevN, + BugReporterContext& BR); + + virtual void registerInitialVisitors(BugReporterContext& BRC, + const ExplodedNode* N) {} +}; + +//===----------------------------------------------------------------------===// +// BugTypes (collections of related reports). +//===----------------------------------------------------------------------===// + +class BugReportEquivClass : public llvm::FoldingSetNode { + // List of *owned* BugReport objects. + std::list<BugReport*> Reports; + + friend class BugReporter; + void AddReport(BugReport* R) { Reports.push_back(R); } +public: + BugReportEquivClass(BugReport* R) { Reports.push_back(R); } + ~BugReportEquivClass(); + + void Profile(llvm::FoldingSetNodeID& ID) const { + assert(!Reports.empty()); + (*Reports.begin())->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; } + }; + + 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()); } + + const_iterator begin() const { return const_iterator(Reports.begin()); } + const_iterator end() const { return const_iterator(Reports.end()); } +}; + + +//===----------------------------------------------------------------------===// +// Specialized subclasses of BugReport. +//===----------------------------------------------------------------------===// + +// FIXME: Collapse this with the default BugReport class. +class RangedBugReport : public BugReport { + std::vector<SourceRange> Ranges; +public: + RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) + : BugReport(D, description, n) {} + + RangedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) + : BugReport(D, shortDescription, description, n) {} + + ~RangedBugReport(); + + // FIXME: Move this out of line. + void addRange(SourceRange R) { + assert(R.isValid()); + Ranges.push_back(R); + } + + // FIXME: Move this out of line. + void getRanges(const SourceRange*& beg, const SourceRange*& end) { + + if (Ranges.empty()) { + beg = NULL; + end = NULL; + } + else { + beg = &Ranges[0]; + end = beg + Ranges.size(); + } + } +}; + +class EnhancedBugReport : public RangedBugReport { +public: + typedef void (*VisitorCreator)(BugReporterContext &BRcC, const void *data, + const ExplodedNode *N); + +private: + typedef std::vector<std::pair<VisitorCreator, const void*> > Creators; + Creators creators; + +public: + EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) + : RangedBugReport(D, description, n) {} + + EnhancedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) + : RangedBugReport(D, shortDescription, description, n) {} + + ~EnhancedBugReport() {} + + void registerInitialVisitors(BugReporterContext& BRC, const ExplodedNode* N) { + for (Creators::iterator I = creators.begin(), E = creators.end(); I!=E; ++I) + I->first(BRC, I->second, N); + } + + void addVisitorCreator(VisitorCreator creator, const void *data) { + creators.push_back(std::make_pair(creator, data)); + } +}; + +//===----------------------------------------------------------------------===// +// BugReporter and friends. +//===----------------------------------------------------------------------===// + +class BugReporterData { +public: + virtual ~BugReporterData(); + virtual Diagnostic& getDiagnostic() = 0; + virtual PathDiagnosticClient* getPathDiagnosticClient() = 0; + virtual ASTContext& getASTContext() = 0; + virtual SourceManager& getSourceManager() = 0; +}; + +class BugReporter { +public: + enum Kind { BaseBRKind, GRBugReporterKind }; + +private: + typedef llvm::ImmutableSet<BugType*> BugTypesTy; + BugTypesTy::Factory F; + BugTypesTy BugTypes; + + const Kind kind; + BugReporterData& D; + + void FlushReport(BugReportEquivClass& EQ); + +protected: + BugReporter(BugReporterData& d, Kind k) : BugTypes(F.GetEmptySet()), kind(k), D(d) {} + +public: + BugReporter(BugReporterData& d) : BugTypes(F.GetEmptySet()), kind(BaseBRKind), D(d) {} + virtual ~BugReporter(); + + void FlushReports(); + + Kind getKind() const { return kind; } + + Diagnostic& getDiagnostic() { + return D.getDiagnostic(); + } + + PathDiagnosticClient* getPathDiagnosticClient() { + return D.getPathDiagnosticClient(); + } + + typedef BugTypesTy::iterator iterator; + iterator begin() { return BugTypes.begin(); } + iterator end() { return BugTypes.end(); } + + ASTContext& getContext() { return D.getASTContext(); } + + SourceManager& getSourceManager() { return D.getSourceManager(); } + + virtual void GeneratePathDiagnostic(PathDiagnostic& PD, + BugReportEquivClass& EQ) {} + + void Register(BugType *BT); + + void EmitReport(BugReport *R); + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, + SourceLocation Loc, + SourceRange* RangeBeg, unsigned NumRanges); + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory, + llvm::StringRef BugStr, SourceLocation Loc, + SourceRange* RangeBeg, unsigned NumRanges); + + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, + SourceLocation Loc) { + EmitBasicReport(BugName, BugStr, Loc, 0, 0); + } + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory, + llvm::StringRef BugStr, SourceLocation Loc) { + EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0); + } + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, + SourceLocation Loc, SourceRange R) { + EmitBasicReport(BugName, BugStr, Loc, &R, 1); + } + + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef Category, + llvm::StringRef BugStr, SourceLocation Loc, + SourceRange R) { + EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1); + } + + static bool classof(const BugReporter* R) { return true; } +}; + +// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. +class GRBugReporter : public BugReporter { + GRExprEngine& Eng; + llvm::SmallSet<SymbolRef, 10> NotableSymbols; +public: + GRBugReporter(BugReporterData& d, GRExprEngine& eng) + : BugReporter(d, GRBugReporterKind), Eng(eng) {} + + virtual ~GRBugReporter(); + + /// getEngine - Return the analysis engine used to analyze a given + /// function or method. + GRExprEngine &getEngine() { return Eng; } + + /// getGraph - Get the exploded graph created by the analysis engine + /// for the analyzed method or function. + ExplodedGraph &getGraph(); + + /// getStateManager - Return the state manager used by the analysis + /// engine. + GRStateManager &getStateManager(); + + virtual void GeneratePathDiagnostic(PathDiagnostic& PD, + BugReportEquivClass& R); + + 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; + } +}; + +class BugReporterContext { + GRBugReporter &BR; + // 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; + llvm::FoldingSet<BugReporterVisitor> CallbacksSet; +public: + BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.GetEmptyList()) {} + virtual ~BugReporterContext(); + + void addVisitor(BugReporterVisitor* visitor); + + typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator; + visitor_iterator visitor_begin() { return Callbacks.begin(); } + visitor_iterator visitor_end() { return Callbacks.end(); } + + GRBugReporter& getBugReporter() { return BR; } + + 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); + } + + GRStateManager& getStateManager() { + return BR.getStateManager(); + } + + ValueManager& getValueManager() { + return getStateManager().getValueManager(); + } + + ASTContext& getASTContext() { + return BR.getContext(); + } + + SourceManager& getSourceManager() { + return BR.getSourceManager(); + } + + virtual BugReport::NodeResolver& getNodeResolver() = 0; +}; + +class DiagBugReport : public RangedBugReport { + std::list<std::string> Strs; + FullSourceLoc L; +public: + DiagBugReport(BugType& D, llvm::StringRef desc, FullSourceLoc l) : + RangedBugReport(D, desc, 0), L(l) {} + + virtual ~DiagBugReport() {} + + // FIXME: Move out-of-line (virtual function). + SourceLocation getLocation() const { return L; } + + void addString(llvm::StringRef s) { Strs.push_back(s); } + + typedef std::list<std::string>::const_iterator str_iterator; + str_iterator str_begin() const { return Strs.begin(); } + str_iterator str_end() const { return Strs.end(); } +}; + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +namespace bugreporter { + +const Stmt *GetDerefExpr(const ExplodedNode *N); +const Stmt *GetDenomExpr(const ExplodedNode *N); +const Stmt *GetCalleeExpr(const ExplodedNode *N); +const Stmt *GetRetValExpr(const ExplodedNode *N); + +void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt, + const ExplodedNode* N); + +void registerFindLastStore(BugReporterContext& BRC, const void *memregion, + const ExplodedNode *N); + +void registerNilReceiverVisitor(BugReporterContext &BRC); + +} // end namespace clang::bugreporter + +//===----------------------------------------------------------------------===// + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugType.h new file mode 100644 index 0000000..afc07c8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/BugType.h @@ -0,0 +1,72 @@ +//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines BugType, a class representing a bug type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE +#define LLVM_CLANG_ANALYSIS_BUGTYPE + +#include "clang/Checker/BugReporter/BugReporter.h" +#include "llvm/ADT/FoldingSet.h" +#include <string> + +namespace clang { + +class ExplodedNode; +class GRExprEngine; + +class BugType { +private: + const std::string Name; + const std::string Category; + llvm::FoldingSet<BugReportEquivClass> EQClasses; + friend class BugReporter; + bool SuppressonSink; +public: + BugType(llvm::StringRef name, llvm::StringRef cat) + : Name(name), Category(cat), SuppressonSink(false) {} + virtual ~BugType(); + + // FIXME: Should these be made strings as well? + llvm::StringRef getName() const { return Name; } + llvm::StringRef getCategory() const { return Category; } + + /// isSuppressOnSink - Returns true if bug reports associated with this bug + /// type should be suppressed if the end node of the report is post-dominated + /// by a sink node. + bool isSuppressOnSink() const { return SuppressonSink; } + void setSuppressOnSink(bool x) { SuppressonSink = x; } + + virtual void FlushReports(BugReporter& BR); + + typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator; + iterator begin() { return EQClasses.begin(); } + iterator end() { return EQClasses.end(); } + + typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator; + const_iterator begin() const { return EQClasses.begin(); } + const_iterator end() const { return EQClasses.end(); } +}; + +class BuiltinBug : public BugType { + const std::string desc; +public: + BuiltinBug(const char *name, const char *description) + : BugType(name, "Logic error"), desc(description) {} + + BuiltinBug(const char *name) + : BugType(name, "Logic error"), desc(name) {} + + llvm::StringRef getDescription() const { return desc; } +}; + +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/PathDiagnostic.h new file mode 100644 index 0000000..24c75ce --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/BugReporter/PathDiagnostic.h @@ -0,0 +1,494 @@ +//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- 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 PathDiagnostic-related interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H +#define LLVM_CLANG_PATH_DIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/FoldingSet.h" +#include <deque> +#include <iterator> +#include <string> +#include <vector> + +namespace clang { + +class Decl; +class SourceManager; +class Stmt; + +//===----------------------------------------------------------------------===// +// High-level interface for handlers of path-sensitive diagnostics. +//===----------------------------------------------------------------------===// + +class PathDiagnostic; + +class PathDiagnosticClient : public DiagnosticClient { +public: + PathDiagnosticClient() {} + + virtual ~PathDiagnosticClient() {} + + virtual void + FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0; + + void FlushDiagnostics(llvm::SmallVectorImpl<std::string> &FilesMade) { + FlushDiagnostics(&FilesMade); + } + + virtual llvm::StringRef getName() const = 0; + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0; + + 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; } +}; + +//===----------------------------------------------------------------------===// +// Path-sensitive diagnostics. +//===----------------------------------------------------------------------===// + +class PathDiagnosticRange : public SourceRange { +public: + const bool isPoint; + + PathDiagnosticRange(const SourceRange &R, bool isP = false) + : SourceRange(R), isPoint(isP) {} +}; + +class PathDiagnosticLocation { +private: + enum Kind { RangeK, SingleLocK, StmtK, DeclK } K; + SourceRange R; + const Stmt *S; + const Decl *D; + const SourceManager *SM; +public: + PathDiagnosticLocation() + : K(SingleLocK), S(0), D(0), SM(0) {} + + PathDiagnosticLocation(FullSourceLoc L) + : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {} + + PathDiagnosticLocation(const Stmt *s, const SourceManager &sm) + : K(StmtK), S(s), D(0), SM(&sm) {} + + PathDiagnosticLocation(SourceRange r, const SourceManager &sm) + : K(RangeK), R(r), S(0), D(0), SM(&sm) {} + + PathDiagnosticLocation(const Decl *d, const SourceManager &sm) + : K(DeclK), S(0), D(d), SM(&sm) {} + + bool operator==(const PathDiagnosticLocation &X) const { + return K == X.K && R == X.R && S == X.S && D == X.D; + } + + bool operator!=(const PathDiagnosticLocation &X) const { + return K != X.K || R != X.R || S != X.S || D != X.D;; + } + + PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) { + K = X.K; + R = X.R; + S = X.S; + D = X.D; + SM = X.SM; + return *this; + } + + bool isValid() const { + return SM != 0; + } + + const SourceManager& getSourceManager() const { assert(isValid());return *SM;} + + FullSourceLoc asLocation() const; + PathDiagnosticRange asRange() const; + const Stmt *asStmt() const { assert(isValid()); return S; } + const Decl *asDecl() const { assert(isValid()); return D; } + + bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; } + + void invalidate() { + *this = PathDiagnosticLocation(); + } + + void flatten(); + + const SourceManager& getManager() const { assert(isValid()); return *SM; } + + void Profile(llvm::FoldingSetNodeID &ID) const; +}; + +class PathDiagnosticLocationPair { +private: + PathDiagnosticLocation Start, End; +public: + PathDiagnosticLocationPair(const PathDiagnosticLocation &start, + const PathDiagnosticLocation &end) + : Start(start), End(end) {} + + const PathDiagnosticLocation &getStart() const { return Start; } + const PathDiagnosticLocation &getEnd() const { return End; } + + void flatten() { + Start.flatten(); + End.flatten(); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + Start.Profile(ID); + End.Profile(ID); + } +}; + +//===----------------------------------------------------------------------===// +// Path "pieces" for path-sensitive diagnostics. +//===----------------------------------------------------------------------===// + +class PathDiagnosticPiece { +public: + enum Kind { ControlFlow, Event, Macro }; + enum DisplayHint { Above, Below }; + +private: + const std::string str; + std::vector<FixItHint> FixItHints; + const Kind kind; + const DisplayHint Hint; + std::vector<SourceRange> ranges; + + // Do not implement: + PathDiagnosticPiece(); + PathDiagnosticPiece(const PathDiagnosticPiece &P); + PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); + +protected: + PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below); + + PathDiagnosticPiece(Kind k, DisplayHint hint = Below); + +public: + virtual ~PathDiagnosticPiece(); + + const std::string& getString() const { return str; } + + /// getDisplayHint - Return a hint indicating where the diagnostic should + /// be displayed by the PathDiagnosticClient. + DisplayHint getDisplayHint() const { return Hint; } + + virtual PathDiagnosticLocation getLocation() const = 0; + virtual void flattenLocations() = 0; + + Kind getKind() const { return kind; } + + void addRange(SourceRange R) { ranges.push_back(R); } + + void addRange(SourceLocation B, SourceLocation E) { + 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 { + return ranges.empty() ? NULL : &ranges[0]; + } + + range_iterator ranges_end() const { + 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 PathDiagnosticSpotPiece : public PathDiagnosticPiece { +private: + PathDiagnosticLocation Pos; +public: + PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, + llvm::StringRef s, + PathDiagnosticPiece::Kind k, + bool addPosRange = true) + : PathDiagnosticPiece(s, k), Pos(pos) { + assert(Pos.asLocation().isValid() && + "PathDiagnosticSpotPiece's must have a valid location."); + if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); + } + + PathDiagnosticLocation getLocation() const { return Pos; } + virtual void flattenLocations() { Pos.flatten(); } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const; +}; + +class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { + +public: + PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, + llvm::StringRef s, bool addPosRange = true) + : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} + + ~PathDiagnosticEventPiece(); + + static inline bool classof(const PathDiagnosticPiece* P) { + return P->getKind() == Event; + } +}; + +class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { + std::vector<PathDiagnosticLocationPair> LPairs; +public: + PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, + const PathDiagnosticLocation &endPos, + llvm::StringRef s) + : PathDiagnosticPiece(s, ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } + + PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, + const PathDiagnosticLocation &endPos) + : PathDiagnosticPiece(ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } + + ~PathDiagnosticControlFlowPiece(); + + PathDiagnosticLocation getStartLocation() const { + assert(!LPairs.empty() && + "PathDiagnosticControlFlowPiece needs at least one location."); + return LPairs[0].getStart(); + } + + PathDiagnosticLocation getEndLocation() const { + assert(!LPairs.empty() && + "PathDiagnosticControlFlowPiece needs at least one location."); + return LPairs[0].getEnd(); + } + + void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); } + + virtual PathDiagnosticLocation getLocation() const { + return getStartLocation(); + } + + typedef std::vector<PathDiagnosticLocationPair>::iterator iterator; + iterator begin() { return LPairs.begin(); } + iterator end() { return LPairs.end(); } + + virtual void flattenLocations() { + for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); + } + + typedef std::vector<PathDiagnosticLocationPair>::const_iterator + const_iterator; + const_iterator begin() const { return LPairs.begin(); } + const_iterator end() const { return LPairs.end(); } + + static inline bool classof(const PathDiagnosticPiece* P) { + return P->getKind() == ControlFlow; + } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const; +}; + +class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { + std::vector<PathDiagnosticPiece*> SubPieces; +public: + PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos) + : PathDiagnosticSpotPiece(pos, "", Macro) {} + + ~PathDiagnosticMacroPiece(); + + 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(); + } + + 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; + } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const; +}; + +/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive +/// 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; + std::string BugType; + std::string Desc; + std::string Category; + std::deque<std::string> OtherDesc; + +public: + PathDiagnostic(); + + PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc, + llvm::StringRef category); + + ~PathDiagnostic(); + + llvm::StringRef getDescription() const { return Desc; } + llvm::StringRef getBugType() const { return BugType; } + llvm::StringRef getCategory() const { return Category; } + + 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(llvm::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());} + + void flattenLocations() { + for (iterator I = begin(), E = end(); I != E; ++I) I->flattenLocations(); + } + + void Profile(llvm::FoldingSetNodeID &ID) const; +}; +} //end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/Checkers/DereferenceChecker.h b/contrib/llvm/tools/clang/include/clang/Checker/Checkers/DereferenceChecker.h new file mode 100644 index 0000000..a84183e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/Checkers/DereferenceChecker.h @@ -0,0 +1,31 @@ +//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines NullDerefChecker and UndefDerefChecker, two builtin checks +// in GRExprEngine that check for null and undefined pointers at loads +// and stores. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DEREFCHECKER +#define LLVM_CLANG_DEREFCHECKER + +#include <utility> + +namespace clang { + +class GRExprEngine; +class ExplodedNode; + +std::pair<ExplodedNode * const *, ExplodedNode * const *> +GetImplicitNullDereferences(GRExprEngine &Eng); + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/Checker/Checkers/LocalCheckers.h new file mode 100644 index 0000000..4a9e381 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/Checkers/LocalCheckers.h @@ -0,0 +1,61 @@ +//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- 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 interface to call a set of intra-procedural (local) +// checkers that use flow/path-sensitive analyses to find bugs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H +#define LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H + +namespace clang { + +class CFG; +class Decl; +class Diagnostic; +class ASTContext; +class PathDiagnosticClient; +class GRTransferFuncs; +class BugType; +class LangOptions; +class ParentMap; +class LiveVariables; +class BugReporter; +class ObjCImplementationDecl; +class LangOptions; +class GRExprEngine; +class TranslationUnitDecl; + +void CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &map, + BugReporter& BR); + +GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, + const LangOptions& lopts); + +void CheckObjCDealloc(const ObjCImplementationDecl* D, const LangOptions& L, + BugReporter& BR); + +void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID, + BugReporter& BR); + +void CheckObjCUnusedIvar(const ObjCImplementationDecl *D, BugReporter& BR); + +void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D); +void RegisterExperimentalChecks(GRExprEngine &Eng); +void RegisterExperimentalInternalChecks(GRExprEngine &Eng); + +void CheckLLVMConventions(TranslationUnitDecl &TU, BugReporter &BR); +void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR); +void CheckSizeofPointer(const Decl *D, BugReporter &BR); + +void RegisterCallInliner(GRExprEngine &Eng); +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/DomainSpecific/CocoaConventions.h b/contrib/llvm/tools/clang/include/clang/Checker/DomainSpecific/CocoaConventions.h new file mode 100644 index 0000000..4bbdab0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/DomainSpecific/CocoaConventions.h @@ -0,0 +1,39 @@ +//===- CocoaConventions.h - Special handling of Cocoa conventions -*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_DS_COCOA +#define LLVM_CLANG_CHECKER_DS_COCOA + +#include "clang/AST/Type.h" + +namespace clang { +namespace cocoa { + + enum NamingConvention { NoConvention, CreateRule, InitRule }; + + NamingConvention deriveNamingConvention(Selector S); + + static inline bool followsFundamentalRule(Selector S) { + return deriveNamingConvention(S) == CreateRule; + } + + bool isRefType(QualType RetTy, llvm::StringRef Prefix, + llvm::StringRef Name = llvm::StringRef()); + + bool isCFObjectRef(QualType T); + + bool isCocoaObjectRef(QualType T); + +}} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/ManagerRegistry.h b/contrib/llvm/tools/clang/include/clang/Checker/ManagerRegistry.h new file mode 100644 index 0000000..ebfd28e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/ManagerRegistry.h @@ -0,0 +1,53 @@ +//===-- ManagerRegistry.h - Pluggable analyzer module registry --*- 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 ManagerRegistry and Register* classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H +#define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H + +#include "clang/Checker/PathSensitive/GRState.h" + +namespace clang { + +/// ManagerRegistry - This class records manager creators registered at +/// runtime. The information is communicated to AnalysisManager through static +/// members. Better design is expected. + +class ManagerRegistry { +public: + static StoreManagerCreator StoreMgrCreator; + static ConstraintManagerCreator ConstraintMgrCreator; +}; + +/// RegisterConstraintManager - This class is used to setup the constraint +/// manager of the static analyzer. The constructor takes a creator function +/// pointer for creating the constraint manager. +/// +/// It is used like this: +/// +/// class MyConstraintManager {}; +/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) { +/// return new MyConstraintManager(statemgr); +/// } +/// RegisterConstraintManager X(CreateMyConstraintManager); + +class RegisterConstraintManager { +public: + RegisterConstraintManager(ConstraintManagerCreator CMC) { + assert(ManagerRegistry::ConstraintMgrCreator == 0 + && "ConstraintMgrCreator already set!"); + ManagerRegistry::ConstraintMgrCreator = CMC; + } +}; + +} +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/AnalysisManager.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/AnalysisManager.h new file mode 100644 index 0000000..3c7cb68 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -0,0 +1,164 @@ +//== AnalysisManager.h - Path sensitive analysis data manager ------*- 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 AnalysisManager class that manages the data and policy +// for path sensitive analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H +#define LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H + +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Checker/BugReporter/BugReporter.h" +#include "clang/Checker/BugReporter/PathDiagnostic.h" + +namespace clang { + +class AnalysisManager : public BugReporterData { + AnalysisContextManager AnaCtxMgr; + LocationContextManager LocCtxMgr; + + ASTContext &Ctx; + Diagnostic &Diags; + const LangOptions &LangInfo; + + llvm::OwningPtr<PathDiagnosticClient> PD; + + // Configurable components creators. + StoreManagerCreator CreateStoreMgr; + ConstraintManagerCreator CreateConstraintMgr; + + enum AnalysisScope { ScopeTU, ScopeDecl } AScope; + + // The maximum number of exploded nodes the analyzer will generate. + unsigned MaxNodes; + + // The maximum number of times the analyzer will go through a loop. + unsigned MaxLoop; + + bool VisualizeEGDot; + bool VisualizeEGUbi; + bool 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. + bool EagerlyAssume; + bool TrimGraph; + bool InlineCall; + +public: + AnalysisManager(ASTContext &ctx, Diagnostic &diags, + const LangOptions &lang, PathDiagnosticClient *pd, + StoreManagerCreator storemgr, + ConstraintManagerCreator constraintmgr, unsigned maxnodes, + unsigned maxloop, + bool vizdot, bool vizubi, bool purge, bool eager, bool trim, + bool inlinecall) + + : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), + CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), + AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop), + VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), + EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {} + + ~AnalysisManager() { FlushDiagnostics(); } + + void ClearContexts() { + LocCtxMgr.clear(); + AnaCtxMgr.clear(); + } + + StoreManagerCreator getStoreManagerCreator() { + return CreateStoreMgr; + } + + ConstraintManagerCreator getConstraintManagerCreator() { + return CreateConstraintMgr; + } + + virtual ASTContext &getASTContext() { + return Ctx; + } + + virtual SourceManager &getSourceManager() { + return getASTContext().getSourceManager(); + } + + virtual Diagnostic &getDiagnostic() { + return Diags; + } + + const LangOptions &getLangOptions() const { + return LangInfo; + } + + virtual PathDiagnosticClient *getPathDiagnosticClient() { + return PD.get(); + } + + void FlushDiagnostics() { + if (PD.get()) + PD->FlushDiagnostics(); + } + + unsigned getMaxNodes() const { return MaxNodes; } + + unsigned getMaxLoop() const { return MaxLoop; } + + bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } + + bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } + + bool shouldVisualize() const { + return VisualizeEGDot || VisualizeEGUbi; + } + + bool shouldTrimGraph() const { return TrimGraph; } + + bool shouldPurgeDead() const { return PurgeDead; } + + bool shouldEagerlyAssume() const { return EagerlyAssume; } + + bool shouldInlineCall() const { return InlineCall; } + + CFG *getCFG(Decl const *D) { + return AnaCtxMgr.getContext(D)->getCFG(); + } + + LiveVariables *getLiveVariables(Decl const *D) { + return AnaCtxMgr.getContext(D)->getLiveVariables(); + } + + ParentMap &getParentMap(Decl const *D) { + return AnaCtxMgr.getContext(D)->getParentMap(); + } + + // Get the top level stack frame. + const StackFrameContext *getStackFrame(Decl const *D) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0); + } + + // Get a stack frame with parent. + StackFrameContext const *getStackFrame(Decl const *D, + LocationContext const *Parent, + Stmt const *S, const CFGBlock *Blk, + unsigned Idx) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx); + } +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/BasicValueFactory.h new file mode 100644 index 0000000..59dd919 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/BasicValueFactory.h @@ -0,0 +1,197 @@ +//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- 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 BasicValueFactory, a class that manages the lifetime +// of APSInt objects and symbolic constraints used by GRExprEngine +// and related classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H +#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H + +#include "clang/Checker/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 { + + class GRState; + +class CompoundValData : public llvm::FoldingSetNode { + QualType T; + llvm::ImmutableList<SVal> L; + +public: + CompoundValData(QualType t, llvm::ImmutableList<SVal> l) + : T(t), L(l) {} + + typedef llvm::ImmutableList<SVal>::iterator iterator; + iterator begin() const { return L.begin(); } + iterator end() const { return L.end(); } + + static void Profile(llvm::FoldingSetNodeID& ID, QualType T, + llvm::ImmutableList<SVal> L); + + void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); } +}; + +class LazyCompoundValData : public llvm::FoldingSetNode { + const void *store; + const TypedRegion *region; +public: + LazyCompoundValData(const void *st, const TypedRegion *r) + : store(st), region(r) {} + + const void *getStore() const { return store; } + const TypedRegion *getRegion() const { return region; } + + static void Profile(llvm::FoldingSetNodeID& ID, const void *store, + const TypedRegion *region); + + void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } +}; + +class BasicValueFactory { + typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> > + APSIntSetTy; + + ASTContext& Ctx; + llvm::BumpPtrAllocator& BPAlloc; + + APSIntSetTy APSIntSet; + void* PersistentSVals; + void* PersistentSValPairs; + + llvm::ImmutableList<SVal>::Factory SValListFactory; + llvm::FoldingSet<CompoundValData> CompoundValDataSet; + llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet; + +public: + BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc) + : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), + SValListFactory(Alloc) {} + + ~BasicValueFactory(); + + ASTContext& getContext() const { return Ctx; } + + const llvm::APSInt& getValue(const llvm::APSInt& X); + const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned); + const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); + const llvm::APSInt& getValue(uint64_t X, QualType T); + + /// Convert - Create a new persistent APSInt with the same value as 'From' + /// but with the bitwidth and signedness of 'To'. + const llvm::APSInt &Convert(const llvm::APSInt& To, + const llvm::APSInt& From) { + + if (To.isUnsigned() == From.isUnsigned() && + To.getBitWidth() == From.getBitWidth()) + return From; + + return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned()); + } + + const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { + assert(T->isIntegerType() || Loc::IsLocType(T)); + unsigned bitwidth = Ctx.getTypeSize(T); + bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T); + + if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth()) + return From; + + return getValue(From.getSExtValue(), bitwidth, isUnsigned); + } + + const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) { + QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy; + return getValue(X, T); + } + + inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { + return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned())); + } + + inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { + return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned())); + } + + inline const llvm::APSInt& getMaxValue(QualType T) { + assert(T->isIntegerType() || Loc::IsLocType(T)); + bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T); + return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned)); + } + + inline const llvm::APSInt& getMinValue(QualType T) { + assert(T->isIntegerType() || Loc::IsLocType(T)); + bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T); + return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned)); + } + + inline const llvm::APSInt& Add1(const llvm::APSInt& V) { + llvm::APSInt X = V; + ++X; + return getValue(X); + } + + inline const llvm::APSInt& Sub1(const llvm::APSInt& V) { + llvm::APSInt X = V; + --X; + return getValue(X); + } + + inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) { + return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); + } + + inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { + return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); + } + + inline const llvm::APSInt& getTruthValue(bool b, QualType T) { + return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); + } + + inline const llvm::APSInt& getTruthValue(bool b) { + return getTruthValue(b, Ctx.IntTy); + } + + const CompoundValData *getCompoundValData(QualType T, + llvm::ImmutableList<SVal> Vals); + + const LazyCompoundValData *getLazyCompoundValData(const void *store, + const TypedRegion *region); + + llvm::ImmutableList<SVal> getEmptySValList() { + return SValListFactory.GetEmptyList(); + } + + llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) { + return SValListFactory.Add(X, L); + } + + const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op, + const llvm::APSInt& V1, + const llvm::APSInt& V2); + + const std::pair<SVal, uintptr_t>& + getPersistentSValWithData(const SVal& V, uintptr_t Data); + + const std::pair<SVal, SVal>& + getPersistentSValPair(const SVal& V1, const SVal& V2); + + const SVal* getPersistentSVal(SVal X); +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Checker.h new file mode 100644 index 0000000..8cb9cc8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Checker.h @@ -0,0 +1,285 @@ +//== Checker.h - Abstract interface for checkers -----------------*- 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 Checker and CheckerVisitor, classes used for creating +// domain-specific checks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CHECKER +#define LLVM_CLANG_ANALYSIS_CHECKER + +#include "clang/Analysis/Support/SaveAndRestore.h" +#include "clang/Checker/PathSensitive/GRExprEngine.h" + +//===----------------------------------------------------------------------===// +// Checker interface. +//===----------------------------------------------------------------------===// + +namespace clang { + +class CheckerContext { + ExplodedNodeSet &Dst; + GRStmtNodeBuilder &B; + GRExprEngine &Eng; + ExplodedNode *Pred; + SaveAndRestore<bool> OldSink; + SaveAndRestore<const void*> OldTag; + SaveAndRestore<ProgramPoint::Kind> OldPointKind; + SaveOr OldHasGen; + const GRState *ST; + const Stmt *statement; + const unsigned size; + bool DoneEvaluating; // FIXME: This is not a permanent API change. +public: + CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, + GRExprEngine &eng, ExplodedNode *pred, + const void *tag, ProgramPoint::Kind K, + const Stmt *stmt = 0, const GRState *st = 0) + : Dst(dst), B(builder), Eng(eng), Pred(pred), + OldSink(B.BuildSinks), + OldTag(B.Tag, tag), + OldPointKind(B.PointKind, K), + OldHasGen(B.HasGeneratedNode), + ST(st), statement(stmt), size(Dst.size()) {} + + ~CheckerContext(); + + GRExprEngine &getEngine() { + return Eng; + } + + AnalysisManager &getAnalysisManager() { + return Eng.getAnalysisManager(); + } + + ConstraintManager &getConstraintManager() { + return Eng.getConstraintManager(); + } + + StoreManager &getStoreManager() { + return Eng.getStoreManager(); + } + + ExplodedNodeSet &getNodeSet() { return Dst; } + GRStmtNodeBuilder &getNodeBuilder() { return B; } + ExplodedNode *&getPredecessor() { return Pred; } + const GRState *getState() { return ST ? ST : B.GetState(Pred); } + + ASTContext &getASTContext() { + return Eng.getContext(); + } + + BugReporter &getBugReporter() { + return Eng.getBugReporter(); + } + + SourceManager &getSourceManager() { + return getBugReporter().getSourceManager(); + } + + ValueManager &getValueManager() { + return Eng.getValueManager(); + } + + SValuator &getSValuator() { + return Eng.getSValuator(); + } + + ExplodedNode *GenerateNode(bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, getState(), false); + if (N && autoTransition) + Dst.Add(N); + return N; + } + + ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state, + bool autoTransition = true) { + assert(state); + ExplodedNode *N = GenerateNodeImpl(stmt, state, false); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *GenerateNode(const GRState *state, ExplodedNode *pred, + bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, false); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) { + return GenerateNodeImpl(stmt, state ? state : getState(), true); + } + + ExplodedNode *GenerateSink(const GRState *state = 0) { + assert(statement && "Only transitions with statements currently supported"); + return GenerateNodeImpl(statement, state ? state : getState(), true); + } + + void addTransition(ExplodedNode *node) { + Dst.Add(node); + } + + void addTransition(const GRState *state) { + assert(state); + // If the 'state' is not new, we need to check if the cached state 'ST' + // is new. + if (state != getState() || (ST && ST != B.GetState(Pred))) + GenerateNode(state, true); + else + Dst.Add(Pred); + } + + // Generate a node with a new program point different from the one that will + // be created by the GRStmtNodeBuilder. + void addTransition(const GRState *state, ProgramPoint Loc) { + ExplodedNode *N = B.generateNode(Loc, state, Pred); + if (N) + addTransition(N); + } + + void EmitReport(BugReport *R) { + Eng.getBugReporter().EmitReport(R); + } + +private: + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, Pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } + + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + ExplodedNode *pred, bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } +}; + +class Checker { +private: + friend class GRExprEngine; + + // FIXME: Remove the 'tag' option. + void GR_Visit(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, + const Stmt *S, + ExplodedNode *Pred, void *tag, bool isPrevisit) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, S); + if (isPrevisit) + _PreVisit(C, S); + else + _PostVisit(C, S); + } + + bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const ObjCMessageExpr *ME, + ExplodedNode *Pred, const GRState *state, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + ME, state); + return EvalNilReceiver(C, ME); + } + + bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const CallExpr *CE, + ExplodedNode *Pred, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + CE); + return EvalCallExpr(C, CE); + } + + // FIXME: Remove the 'tag' option. + void GR_VisitBind(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, GRExprEngine &Eng, + const Stmt *AssignE, + const Stmt *StoreE, ExplodedNode *Pred, void *tag, + SVal location, SVal val, + bool isPrevisit) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, StoreE); + assert(isPrevisit && "Only previsit supported for now."); + PreVisitBind(C, AssignE, StoreE, location, val); + } + + // FIXME: Remove the 'tag' option. + void GR_VisitLocation(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, + const Stmt *S, + ExplodedNode *Pred, const GRState *state, + SVal location, + void *tag, bool isLoad) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isLoad ? ProgramPoint::PreLoadKind : + ProgramPoint::PreStoreKind, S, state); + VisitLocation(C, S, location); + } + + void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, + SymbolReaper &SymReaper, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + ProgramPoint::PostPurgeDeadSymbolsKind, S); + EvalDeadSymbols(C, S, SymReaper); + } + +public: + virtual ~Checker(); + virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} + virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} + virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} + virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, + const Stmt *StoreE, SVal location, SVal val) {} + virtual void EvalDeadSymbols(CheckerContext &C, const Stmt *S, + SymbolReaper &SymReaper) {} + virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) {} + + virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, + GRExprEngine &Eng, + Stmt *Condition, void *tag) {} + + virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { + return false; + } + + virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { + return false; + } + + virtual const GRState *EvalAssume(const GRState *state, SVal Cond, + bool Assumption) { + return state; + } +}; +} // end clang namespace + +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def new file mode 100644 index 0000000..2edc4a3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def @@ -0,0 +1,37 @@ +//===-- CheckerVisitor.def - Metadata for CheckerVisitor ----------------*-===// +// +// 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 AST nodes accepted by the CheckerVisitor class. +// +//===---------------------------------------------------------------------===// + +#ifndef PREVISIT +#define PREVISIT(NODE, FALLBACK) +#endif + +#ifndef POSTVISIT +#define POSTVISIT(NODE, FALLBACK) +#endif + +PREVISIT(ArraySubscriptExpr, Stmt) +PREVISIT(BinaryOperator, Stmt) +PREVISIT(CallExpr, Stmt) +PREVISIT(CXXOperatorCallExpr, CallExpr) +PREVISIT(DeclStmt, Stmt) +PREVISIT(ObjCMessageExpr, Stmt) +PREVISIT(ReturnStmt, Stmt) + +POSTVISIT(BlockExpr, Stmt) +POSTVISIT(BinaryOperator, Stmt) +POSTVISIT(CallExpr, Stmt) +POSTVISIT(CXXOperatorCallExpr, CallExpr) +POSTVISIT(ObjCMessageExpr, Stmt) + +#undef PREVISIT +#undef POSTVISIT diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.h new file mode 100644 index 0000000..72f0ae1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/CheckerVisitor.h @@ -0,0 +1,102 @@ +//== CheckerVisitor.h - Abstract visitor for checkers ------------*- 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 CheckerVisitor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CHECKERVISITOR +#define LLVM_CLANG_ANALYSIS_CHECKERVISITOR +#include "clang/Checker/PathSensitive/Checker.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +// Checker visitor interface. Used by subclasses of Checker to specify their +// own checker visitor logic. +//===----------------------------------------------------------------------===// + +/// CheckerVisitor - This class implements a simple visitor for Stmt subclasses. +/// Since Expr derives from Stmt, this also includes support for visiting Exprs. +template<typename ImplClass> +class CheckerVisitor : public Checker { +public: + virtual void _PreVisit(CheckerContext &C, const Stmt *S) { + PreVisit(C, S); + } + + virtual void _PostVisit(CheckerContext &C, const Stmt *S) { + PostVisit(C, S); + } + + void PreVisit(CheckerContext &C, const Stmt *S) { + switch (S->getStmtClass()) { + default: + assert(false && "Unsupport statement."); + return; + + case Stmt::ImplicitCastExprClass: + case Stmt::CStyleCastExprClass: + static_cast<ImplClass*>(this)->PreVisitCastExpr(C, + static_cast<const CastExpr*>(S)); + break; + + case Stmt::CompoundAssignOperatorClass: + static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C, + static_cast<const BinaryOperator*>(S)); + break; + +#define PREVISIT(NAME, FALLBACK) \ +case Stmt::NAME ## Class:\ +static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ +break; +#include "clang/Checker/PathSensitive/CheckerVisitor.def" + } + } + + void PostVisit(CheckerContext &C, const Stmt *S) { + switch (S->getStmtClass()) { + default: + assert(false && "Unsupport statement."); + return; + case Stmt::CompoundAssignOperatorClass: + static_cast<ImplClass*>(this)->PostVisitBinaryOperator(C, + static_cast<const BinaryOperator*>(S)); + break; + +#define POSTVISIT(NAME, FALLBACK) \ +case Stmt::NAME ## Class:\ +static_cast<ImplClass*>(this)->\ +PostVisit ## NAME(C,static_cast<const NAME*>(S));\ +break; +#include "clang/Checker/PathSensitive/CheckerVisitor.def" + } + } + + void PreVisitStmt(CheckerContext &C, const Stmt *S) {} + void PostVisitStmt(CheckerContext &C, const Stmt *S) {} + + void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) { + static_cast<ImplClass*>(this)->PreVisitStmt(C, E); + } + +#define PREVISIT(NAME, FALLBACK) \ +void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ + static_cast<ImplClass*>(this)->PreVisit ## FALLBACK(C, S);\ +} +#define POSTVISIT(NAME, FALLBACK) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ + static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\ +} +#include "clang/Checker/PathSensitive/CheckerVisitor.def" +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ConstraintManager.h new file mode 100644 index 0000000..ce7d1b3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ConstraintManager.h @@ -0,0 +1,75 @@ +//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the interface to manage constraints on symbolic values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H +#define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H + +// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place. +#include "clang/Checker/PathSensitive/Store.h" + +namespace llvm { +class APSInt; +} + +namespace clang { + +class GRState; +class GRStateManager; +class GRSubEngine; +class SVal; + +class ConstraintManager { +public: + virtual ~ConstraintManager(); + virtual const GRState *Assume(const GRState *state, DefinedSVal Cond, + bool Assumption) = 0; + + virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx, + DefinedSVal UpperBound, bool Assumption) = 0; + + std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state, + DefinedSVal Cond) { + return std::make_pair(Assume(state, Cond, true), + Assume(state, Cond, false)); + } + + virtual const llvm::APSInt* getSymVal(const GRState *state, + SymbolRef sym) const = 0; + + virtual bool isEqual(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) const = 0; + + virtual const GRState *RemoveDeadBindings(const GRState *state, + SymbolReaper& SymReaper) = 0; + + virtual void print(const GRState *state, llvm::raw_ostream& Out, + const char* nl, const char *sep) = 0; + + virtual void EndPath(const GRState *state) {} + + /// 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 + /// GRExprEngine to determine if the value should be replaced with a + /// conjured symbolic value in order to recover some precision. + virtual bool canReasonAbout(SVal X) const = 0; +}; + +ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr, + GRSubEngine &subengine); +ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr, + GRSubEngine &subengine); + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Environment.h new file mode 100644 index 0000000..b9bbebc --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Environment.h @@ -0,0 +1,96 @@ +//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the Environment and EnvironmentManager classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_ENVIRONMENT_H +#define LLVM_CLANG_ANALYSIS_ENVIRONMENT_H + +// For using typedefs in StoreManager. Should find a better place for these +// typedefs. +#include "clang/Checker/PathSensitive/Store.h" + +#include "clang/Checker/PathSensitive/SVals.h" +#include "llvm/ADT/ImmutableMap.h" + +namespace clang { + +class EnvironmentManager; +class ValueManager; +class LiveVariables; + + +class Environment { +private: + friend class EnvironmentManager; + + // Type definitions. + typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy; + + // Data. + BindingsTy ExprBindings; + + Environment(BindingsTy eb) + : ExprBindings(eb) {} + +public: + typedef BindingsTy::iterator iterator; + iterator begin() const { return ExprBindings.begin(); } + iterator end() const { return ExprBindings.end(); } + + SVal LookupExpr(const Stmt* E) const { + const SVal* X = ExprBindings.lookup(E); + return X ? *X : UnknownVal(); + } + + SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const; + + /// Profile - Profile the contents of an Environment object for use + /// in a FoldingSet. + static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) { + E->ExprBindings.Profile(ID); + } + + /// Profile - Used to profile the contents of this object for inclusion + /// in a FoldingSet. + void Profile(llvm::FoldingSetNodeID& ID) const { + Profile(ID, this); + } + + bool operator==(const Environment& RHS) const { + return ExprBindings == RHS.ExprBindings; + } +}; + +class EnvironmentManager { +private: + typedef Environment::BindingsTy::Factory FactoryTy; + FactoryTy F; + +public: + EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {} + ~EnvironmentManager() {} + + Environment getInitialEnvironment() { + return Environment(F.GetEmptyMap()); + } + + Environment BindExpr(Environment Env, const Stmt *S, SVal V, + bool Invalidate); + + Environment RemoveDeadBindings(Environment Env, const Stmt *S, + SymbolReaper &SymReaper, const GRState *ST, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ExplodedGraph.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ExplodedGraph.h new file mode 100644 index 0000000..c09c893 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ExplodedGraph.h @@ -0,0 +1,436 @@ +//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded 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 defines the template classes ExplodedNode and ExplodedGraph, +// which represent a path-sensitive, intra-procedural "exploded graph." +// See "Precise interprocedural dataflow analysis via graph reachability" +// by Reps, Horwitz, and Sagiv +// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an +// exploded graph. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH +#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH + +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/AST/Decl.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/Support/Casting.h" +#include "clang/Analysis/Support/BumpVector.h" + +namespace clang { + +class GRState; +class CFG; +class ASTContext; +class ExplodedGraph; + +//===----------------------------------------------------------------------===// +// ExplodedGraph "implementation" classes. These classes are not typed to +// contain a specific kind of state. Typed-specialized versions are defined +// on top of these classes. +//===----------------------------------------------------------------------===// + +class ExplodedNode : public llvm::FoldingSetNode { + friend class ExplodedGraph; + friend class GRCoreEngine; + friend class GRStmtNodeBuilder; + friend class GRBranchNodeBuilder; + friend class GRIndirectGotoNodeBuilder; + friend class GRSwitchNodeBuilder; + friend class GREndPathNodeBuilder; + + class NodeGroup { + enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 }; + uintptr_t P; + + unsigned getKind() const { + return P & 0x1; + } + + void* getPtr() const { + assert (!getFlag()); + return reinterpret_cast<void*>(P & ~Mask); + } + + ExplodedNode *getNode() const { + return reinterpret_cast<ExplodedNode*>(getPtr()); + } + + public: + NodeGroup() : P(0) {} + + ExplodedNode **begin() const; + + ExplodedNode **end() const; + + unsigned size() const; + + bool empty() const { return (P & ~Mask) == 0; } + + void addNode(ExplodedNode* N, ExplodedGraph &G); + + void setFlag() { + assert(P == 0); + P = AuxFlag; + } + + bool getFlag() const { + return P & AuxFlag ? true : false; + } + }; + + /// Location - The program location (within a function body) associated + /// with this node. + const ProgramPoint Location; + + /// State - The state associated with this node. + const GRState* State; + + /// Preds - The predecessors of this node. + NodeGroup Preds; + + /// Succs - The successors of this node. + NodeGroup Succs; + +public: + + explicit ExplodedNode(const ProgramPoint& loc, const GRState* state) + : Location(loc), State(state) {} + + /// getLocation - Returns the edge associated with the given node. + ProgramPoint getLocation() const { return Location; } + + const LocationContext *getLocationContext() const { + return getLocation().getLocationContext(); + } + + const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } + + CFG &getCFG() const { return *getLocationContext()->getCFG(); } + + ParentMap &getParentMap() const {return getLocationContext()->getParentMap();} + + LiveVariables &getLiveVariables() const { + return *getLocationContext()->getLiveVariables(); + } + + const GRState* 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 GRState* state) { + ID.Add(Loc); + ID.AddPointer(state); + } + + void Profile(llvm::FoldingSetNodeID& ID) const { + Profile(ID, getLocation(), getState()); + } + + /// addPredeccessor - Adds a predecessor to the current node, and + /// in tandem add this node as a successor of the other node. + void addPredecessor(ExplodedNode* V, ExplodedGraph &G); + + unsigned succ_size() const { return Succs.size(); } + unsigned pred_size() const { return Preds.size(); } + bool succ_empty() const { return Succs.empty(); } + bool pred_empty() const { return Preds.empty(); } + + bool isSink() const { return Succs.getFlag(); } + void markAsSink() { Succs.setFlag(); } + + ExplodedNode* getFirstPred() { + return pred_empty() ? NULL : *(pred_begin()); + } + + const ExplodedNode* getFirstPred() const { + return const_cast<ExplodedNode*>(this)->getFirstPred(); + } + + // Iterators over successor and predecessor vertices. + typedef ExplodedNode** succ_iterator; + typedef const ExplodedNode* const * const_succ_iterator; + typedef ExplodedNode** pred_iterator; + typedef const ExplodedNode* const * const_pred_iterator; + + pred_iterator pred_begin() { return Preds.begin(); } + pred_iterator pred_end() { return Preds.end(); } + + const_pred_iterator pred_begin() const { + return const_cast<ExplodedNode*>(this)->pred_begin(); + } + const_pred_iterator pred_end() const { + return const_cast<ExplodedNode*>(this)->pred_end(); + } + + succ_iterator succ_begin() { return Succs.begin(); } + succ_iterator succ_end() { return Succs.end(); } + + const_succ_iterator succ_begin() const { + return const_cast<ExplodedNode*>(this)->succ_begin(); + } + const_succ_iterator succ_end() const { + return const_cast<ExplodedNode*>(this)->succ_end(); + } + + // For debugging. + +public: + + class Auditor { + public: + virtual ~Auditor(); + virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst) = 0; + }; + + static void SetAuditor(Auditor* A); +}; + +// FIXME: Is this class necessary? +class InterExplodedGraphMap { + llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M; + friend class ExplodedGraph; + +public: + ExplodedNode* getMappedNode(const ExplodedNode* N) const; + + InterExplodedGraphMap() {} + virtual ~InterExplodedGraphMap() {} +}; + +class ExplodedGraph { +protected: + friend class GRCoreEngine; + + // Type definitions. + typedef llvm::SmallVector<ExplodedNode*,2> RootsTy; + typedef llvm::SmallVector<ExplodedNode*,10> EndNodesTy; + + /// Roots - 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; + + /// EndNodes - The nodes in the simulation graph which have been + /// specially marked as the endpoint of an abstract simulation path. + EndNodesTy EndNodes; + + /// Nodes - The nodes in the graph. + llvm::FoldingSet<ExplodedNode> Nodes; + + /// BVC - Allocator and context for allocating nodes and their predecessor + /// and successor groups. + BumpVectorContext BVC; + + /// Ctx - The ASTContext used to "interpret" CodeDecl. + ASTContext& Ctx; + + /// NumNodes - The number of nodes in the graph. + unsigned NumNodes; + +public: + /// getNode - 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 + /// the node was freshly created. + + ExplodedNode* getNode(const ProgramPoint& L, const GRState *State, + bool* IsNew = 0); + + ExplodedGraph* MakeEmptyGraph() const { + return new ExplodedGraph(Ctx); + } + + /// addRoot - Add an untyped node to the set of roots. + ExplodedNode* addRoot(ExplodedNode* V) { + Roots.push_back(V); + return V; + } + + /// addEndOfPath - Add an untyped node to the set of EOP nodes. + ExplodedNode* addEndOfPath(ExplodedNode* V) { + EndNodes.push_back(V); + return V; + } + + ExplodedGraph(ASTContext& ctx) : Ctx(ctx), NumNodes(0) {} + + ~ExplodedGraph() {} + + unsigned num_roots() const { return Roots.size(); } + unsigned num_eops() const { return EndNodes.size(); } + + bool empty() const { return NumNodes == 0; } + unsigned size() const { return NumNodes; } + + // 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 AllNodesTy::iterator node_iterator; + typedef AllNodesTy::const_iterator const_node_iterator; + + node_iterator nodes_begin() { return Nodes.begin(); } + + node_iterator nodes_end() { return Nodes.end(); } + + const_node_iterator nodes_begin() const { return Nodes.begin(); } + + const_node_iterator nodes_end() const { return Nodes.end(); } + + roots_iterator roots_begin() { return Roots.begin(); } + + roots_iterator roots_end() { return Roots.end(); } + + const_roots_iterator roots_begin() const { return Roots.begin(); } + + const_roots_iterator roots_end() const { return Roots.end(); } + + eop_iterator eop_begin() { return EndNodes.begin(); } + + eop_iterator eop_end() { return EndNodes.end(); } + + const_eop_iterator eop_begin() const { return EndNodes.begin(); } + + const_eop_iterator eop_end() const { return EndNodes.end(); } + + llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); } + BumpVectorContext &getNodeAllocator() { return BVC; } + + ASTContext& getContext() { return Ctx; } + + typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; + + std::pair<ExplodedGraph*, InterExplodedGraphMap*> + Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd, + llvm::DenseMap<const void*, const void*> *InverseMap = 0) const; + + ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg, + const ExplodedNode* const * NEnd, + InterExplodedGraphMap *M, + llvm::DenseMap<const void*, const void*> *InverseMap) const; +}; + +class ExplodedNodeSet { + typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy; + ImplTy Impl; + +public: + ExplodedNodeSet(ExplodedNode* N) { + assert (N && !static_cast<ExplodedNode*>(N)->isSink()); + Impl.insert(N); + } + + ExplodedNodeSet() {} + + inline void Add(ExplodedNode* N) { + 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(); } + + void clear() { Impl.clear(); } + void insert(const ExplodedNodeSet &S) { + if (empty()) + Impl = S.Impl; + else + Impl.insert(S.begin(), S.end()); + } + + inline iterator begin() { return Impl.begin(); } + inline iterator end() { return Impl.end(); } + + inline const_iterator begin() const { return Impl.begin(); } + inline const_iterator end() const { return Impl.end(); } +}; + +} // end clang namespace + +// GraphTraits + +namespace llvm { + template<> struct GraphTraits<clang::ExplodedNode*> { + typedef clang::ExplodedNode NodeType; + typedef NodeType::succ_iterator ChildIteratorType; + typedef llvm::df_iterator<NodeType*> nodes_iterator; + + static inline NodeType* getEntryNode(NodeType* N) { + return N; + } + + static inline ChildIteratorType child_begin(NodeType* N) { + return N->succ_begin(); + } + + static inline ChildIteratorType child_end(NodeType* N) { + return N->succ_end(); + } + + static inline nodes_iterator nodes_begin(NodeType* N) { + return df_begin(N); + } + + static inline nodes_iterator nodes_end(NodeType* N) { + return df_end(N); + } + }; + + template<> struct GraphTraits<const clang::ExplodedNode*> { + typedef const clang::ExplodedNode NodeType; + typedef NodeType::const_succ_iterator ChildIteratorType; + typedef llvm::df_iterator<NodeType*> nodes_iterator; + + static inline NodeType* getEntryNode(NodeType* N) { + return N; + } + + static inline ChildIteratorType child_begin(NodeType* N) { + return N->succ_begin(); + } + + static inline ChildIteratorType child_end(NodeType* N) { + return N->succ_end(); + } + + static inline nodes_iterator nodes_begin(NodeType* N) { + return df_begin(N); + } + + static inline nodes_iterator nodes_end(NodeType* N) { + return df_end(N); + } + }; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRAuditor.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRAuditor.h new file mode 100644 index 0000000..015c82e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRAuditor.h @@ -0,0 +1,35 @@ +//==- GRAuditor.h - Observers of the creation of ExplodedNodes------*- 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 GRAuditor and its primary subclasses, an interface +// to audit the creation of ExplodedNodes. This interface can be used +// to implement simple checkers that do not mutate analysis state but +// instead operate by perfoming simple logical checks at key monitoring +// locations (e.g., function calls). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRAUDITOR +#define LLVM_CLANG_ANALYSIS_GRAUDITOR + +namespace clang { + +class ExplodedNode; +class GRStateManager; + +class GRAuditor { +public: + virtual ~GRAuditor() {} + virtual bool Audit(ExplodedNode* N, GRStateManager& M) = 0; +}; + + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRBlockCounter.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRBlockCounter.h new file mode 100644 index 0000000..b7d0e8a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRBlockCounter.h @@ -0,0 +1,55 @@ +//==- GRBlockCounter.h - ADT for counting block visits -------------*- 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 GRBlockCounter, an abstract data type used to count +// the number of times a given block has been visited along a path +// analyzed by GRCoreEngine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER +#define LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER + +namespace llvm { + class BumpPtrAllocator; +} + +namespace clang { + +class StackFrameContext; + +class GRBlockCounter { + void* Data; + + GRBlockCounter(void* D) : Data(D) {} + +public: + GRBlockCounter() : Data(0) {} + + unsigned getNumVisited(const StackFrameContext *CallSite, + unsigned BlockID) const; + + class Factory { + void* F; + public: + Factory(llvm::BumpPtrAllocator& Alloc); + ~Factory(); + + GRBlockCounter GetEmptyCounter(); + GRBlockCounter IncrementCount(GRBlockCounter BC, + const StackFrameContext *CallSite, + unsigned BlockID); + }; + + friend class Factory; +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRCoreEngine.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRCoreEngine.h new file mode 100644 index 0000000..2d8afee --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -0,0 +1,487 @@ +//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine --------------*- 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 generic engine for intraprocedural, path-sensitive, +// dataflow analysis via graph reachability. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRENGINE +#define LLVM_CLANG_ANALYSIS_GRENGINE + +#include "clang/AST/Expr.h" +#include "clang/Checker/PathSensitive/ExplodedGraph.h" +#include "clang/Checker/PathSensitive/GRWorkList.h" +#include "clang/Checker/PathSensitive/GRBlockCounter.h" +#include "clang/Checker/PathSensitive/GRAuditor.h" +#include "clang/Checker/PathSensitive/GRSubEngine.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +/// GRCoreEngine - Implements the core logic of the graph-reachability +/// analysis. It traverses the CFG and generates the ExplodedGraph. +/// Program "states" are treated as opaque void pointers. +/// The template class GRCoreEngine (which subclasses GRCoreEngine) +/// provides the matching component to the engine that knows the actual types +/// for states. Note that this engine only dispatches to transfer functions +/// at the statement and block-level. The analyses themselves must implement +/// any transfer function logic and the sub-expression level (if any). +class GRCoreEngine { + friend class GRStmtNodeBuilder; + friend class GRBranchNodeBuilder; + friend class GRIndirectGotoNodeBuilder; + friend class GRSwitchNodeBuilder; + friend class GREndPathNodeBuilder; + friend class GRCallEnterNodeBuilder; + friend class GRCallExitNodeBuilder; + + GRSubEngine& SubEngine; + + /// G - The simulation graph. Each node is a (location,state) pair. + llvm::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 + /// the order that nodes are processed. + GRWorkList* WList; + + /// BCounterFactory - A factory object for created GRBlockCounter objects. + /// These are used to record for key nodes in the ExplodedGraph the + /// number of times different CFGBlocks have been visited along a path. + GRBlockCounter::Factory BCounterFactory; + + void GenerateNode(const ProgramPoint& Loc, const GRState* State, + ExplodedNode* Pred); + + void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); + void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); + void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred); + void HandlePostStmt(const PostStmt& S, CFGBlock* B, + unsigned StmtIdx, ExplodedNode *Pred); + + void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, + ExplodedNode* Pred); + void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, + unsigned Index, ExplodedNode *Pred); + void HandleCallExit(const CallExit &L, ExplodedNode *Pred); + + /// Get the initial state from the subengine. + const GRState* getInitialState(const LocationContext *InitLoc) { + return SubEngine.getInitialState(InitLoc); + } + + void ProcessEndPath(GREndPathNodeBuilder& Builder); + + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); + + bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, + GRBlockCounter BC); + + + void ProcessBranch(Stmt* Condition, Stmt* Terminator, + GRBranchNodeBuilder& Builder); + + + void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder); + + + void ProcessSwitch(GRSwitchNodeBuilder& Builder); + + void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); + void ProcessCallExit(GRCallExitNodeBuilder &Builder); + +private: + GRCoreEngine(const GRCoreEngine&); // Do not implement. + GRCoreEngine& operator=(const GRCoreEngine&); + +public: + /// Construct a GRCoreEngine object to analyze the provided CFG using + /// a DFS exploration of the exploded graph. + GRCoreEngine(ASTContext& ctx, GRSubEngine& subengine) + : SubEngine(subengine), G(new ExplodedGraph(ctx)), + WList(GRWorkList::MakeBFS()), + BCounterFactory(G->getAllocator()) {} + + /// Construct a GRCoreEngine object to analyze the provided CFG and to + /// use the provided worklist object to execute the worklist algorithm. + /// The GRCoreEngine object assumes ownership of 'wlist'. + GRCoreEngine(ASTContext& ctx, GRWorkList* wlist, GRSubEngine& subengine) + : SubEngine(subengine), G(new ExplodedGraph(ctx)), WList(wlist), + BCounterFactory(G->getAllocator()) {} + + ~GRCoreEngine() { + delete WList; + } + + /// getGraph - Returns the exploded graph. + ExplodedGraph& getGraph() { return *G.get(); } + + /// takeGraph - Returns the exploded graph. Ownership of the graph is + /// transfered to the caller. + ExplodedGraph* takeGraph() { return G.take(); } + + /// 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); +}; + +class GRStmtNodeBuilder { + GRCoreEngine& Eng; + CFGBlock& B; + const unsigned Idx; + ExplodedNode* Pred; + GRStateManager& Mgr; + GRAuditor* Auditor; + +public: + bool PurgingDeadSymbols; + bool BuildSinks; + bool HasGeneratedNode; + ProgramPoint::Kind PointKind; + const void *Tag; + + const GRState* CleanedState; + + + typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy; + DeferredTy Deferred; + + void GenerateAutoTransition(ExplodedNode* N); + +public: + GRStmtNodeBuilder(CFGBlock* b, unsigned idx, ExplodedNode* N, + GRCoreEngine* e, GRStateManager &mgr); + + ~GRStmtNodeBuilder(); + + ExplodedNode* getBasePredecessor() const { return Pred; } + + // FIXME: This should not be exposed. + GRWorkList *getWorkList() { return Eng.WList; } + + void SetCleanedState(const GRState* St) { + CleanedState = St; + } + + GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + + unsigned getCurrentBlockCount() const { + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); + } + + ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { + HasGeneratedNode = true; + return generateNodeInternal(PP, St, Pred); + } + + ExplodedNode* generateNode(const Stmt *S, const GRState *St, + ExplodedNode *Pred, ProgramPoint::Kind K) { + HasGeneratedNode = true; + + if (PurgingDeadSymbols) + K = ProgramPoint::PostPurgeDeadSymbolsKind; + + return generateNodeInternal(S, St, Pred, K, Tag); + } + + ExplodedNode* generateNode(const Stmt *S, const GRState *St, + ExplodedNode *Pred) { + return generateNode(S, St, Pred, PointKind); + } + + ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, + ExplodedNode* Pred) { + HasGeneratedNode = true; + return generateNodeInternal(PP, State, Pred); + } + + ExplodedNode* + generateNodeInternal(const ProgramPoint &PP, const GRState* State, + ExplodedNode* Pred); + + ExplodedNode* + generateNodeInternal(const Stmt* S, const GRState* State, ExplodedNode* Pred, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind, + const void *tag = 0); + + /// getStmt - Return the current block-level expression associated with + /// this builder. + Stmt* getStmt() const { return B[Idx]; } + + /// getBlock - Return the CFGBlock associated with the block-level expression + /// of this builder. + CFGBlock* getBlock() const { return &B; } + + unsigned getIndex() const { return Idx; } + + void setAuditor(GRAuditor* A) { Auditor = A; } + + const GRState* GetState(ExplodedNode* Pred) const { + if (Pred == getBasePredecessor()) + return CleanedState; + else + return Pred->getState(); + } + + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St) { + return MakeNode(Dst, S, Pred, St, PointKind); + } + + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St, ProgramPoint::Kind K); + + ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S, + ExplodedNode* Pred, const GRState* St) { + bool Tmp = BuildSinks; + BuildSinks = true; + ExplodedNode* N = MakeNode(Dst, S, Pred, St); + BuildSinks = Tmp; + return N; + } +}; + +class GRBranchNodeBuilder { + GRCoreEngine& Eng; + CFGBlock* Src; + CFGBlock* DstT; + CFGBlock* DstF; + ExplodedNode* Pred; + + typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy; + DeferredTy Deferred; + + bool GeneratedTrue; + bool GeneratedFalse; + bool InFeasibleTrue; + bool InFeasibleFalse; + +public: + GRBranchNodeBuilder(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF, + ExplodedNode* pred, GRCoreEngine* e) + : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), + GeneratedTrue(false), GeneratedFalse(false), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} + + ~GRBranchNodeBuilder(); + + ExplodedNode* getPredecessor() const { return Pred; } + + const ExplodedGraph& getGraph() const { return *Eng.G; } + + GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + + ExplodedNode* generateNode(const GRState* State, bool branch); + + CFGBlock* getTargetBlock(bool branch) const { + return branch ? DstT : DstF; + } + + void markInfeasible(bool branch) { + if (branch) + InFeasibleTrue = GeneratedTrue = true; + else + InFeasibleFalse = GeneratedFalse = true; + } + + bool isFeasible(bool branch) { + return branch ? !InFeasibleTrue : !InFeasibleFalse; + } + + const GRState* getState() const { + return getPredecessor()->getState(); + } +}; + +class GRIndirectGotoNodeBuilder { + GRCoreEngine& Eng; + CFGBlock* Src; + CFGBlock& DispatchBlock; + Expr* E; + ExplodedNode* Pred; + +public: + GRIndirectGotoNodeBuilder(ExplodedNode* pred, CFGBlock* src, Expr* e, + CFGBlock* dispatch, GRCoreEngine* eng) + : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} + + class iterator { + CFGBlock::succ_iterator I; + + friend class GRIndirectGotoNodeBuilder; + iterator(CFGBlock::succ_iterator i) : I(i) {} + public: + + iterator& operator++() { ++I; return *this; } + bool operator!=(const iterator& X) const { return I != X.I; } + + LabelStmt* getLabel() const { + return llvm::cast<LabelStmt>((*I)->getLabel()); + } + + CFGBlock* getBlock() const { + return *I; + } + }; + + iterator begin() { return iterator(DispatchBlock.succ_begin()); } + iterator end() { return iterator(DispatchBlock.succ_end()); } + + ExplodedNode* generateNode(const iterator& I, const GRState* State, + bool isSink = false); + + Expr* getTarget() const { return E; } + + const GRState* getState() const { return Pred->State; } +}; + +class GRSwitchNodeBuilder { + GRCoreEngine& Eng; + CFGBlock* Src; + Expr* Condition; + ExplodedNode* Pred; + +public: + GRSwitchNodeBuilder(ExplodedNode* pred, CFGBlock* src, + Expr* condition, GRCoreEngine* eng) + : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} + + class iterator { + CFGBlock::succ_reverse_iterator I; + + friend class GRSwitchNodeBuilder; + iterator(CFGBlock::succ_reverse_iterator i) : I(i) {} + + public: + iterator& operator++() { ++I; return *this; } + bool operator!=(const iterator& X) const { return I != X.I; } + + CaseStmt* getCase() const { + return llvm::cast<CaseStmt>((*I)->getLabel()); + } + + CFGBlock* getBlock() const { + return *I; + } + }; + + iterator begin() { return iterator(Src->succ_rbegin()+1); } + iterator end() { return iterator(Src->succ_rend()); } + + ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State); + + ExplodedNode* generateDefaultCaseNode(const GRState* State, + bool isSink = false); + + Expr* getCondition() const { return Condition; } + + const GRState* getState() const { return Pred->State; } +}; + +class GREndPathNodeBuilder { + GRCoreEngine &Eng; + CFGBlock& B; + ExplodedNode* Pred; + +public: + bool HasGeneratedNode; + +public: + GREndPathNodeBuilder(CFGBlock* b, ExplodedNode* N, GRCoreEngine* e) + : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} + + ~GREndPathNodeBuilder(); + + GRWorkList &getWorkList() { return *Eng.WList; } + + ExplodedNode* getPredecessor() const { return Pred; } + + GRBlockCounter getBlockCounter() const { + return Eng.WList->getBlockCounter(); + } + + unsigned getCurrentBlockCount() const { + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); + } + + ExplodedNode* generateNode(const GRState* State, const void *tag = 0, + ExplodedNode *P = 0); + + void GenerateCallExitNode(const GRState *state); + + CFGBlock* getBlock() const { return &B; } + + const GRState* getState() const { + return getPredecessor()->getState(); + } +}; + +class GRCallEnterNodeBuilder { + GRCoreEngine &Eng; + + const ExplodedNode *Pred; + + // The call site. + const Stmt *CE; + + // The definition of callee. + const FunctionDecl *FD; + + // The parent block of the CallExpr. + const CFGBlock *Block; + + // The CFGBlock index of the CallExpr. + unsigned Index; + +public: + GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, + const Stmt *s, const FunctionDecl *fd, + const CFGBlock *blk, unsigned idx) + : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} + + const GRState *getState() const { return Pred->getState(); } + + const LocationContext *getLocationContext() const { + return Pred->getLocationContext(); + } + + const Stmt *getCallExpr() const { return CE; } + + const FunctionDecl *getCallee() const { return FD; } + + const CFGBlock *getBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + + void GenerateNode(const GRState *state, const LocationContext *LocCtx); +}; + +class GRCallExitNodeBuilder { + GRCoreEngine &Eng; + const ExplodedNode *Pred; + +public: + GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred) + : Eng(eng), Pred(pred) {} + + const ExplodedNode *getPredecessor() const { return Pred; } + + const GRState *getState() const { return Pred->getState(); } + + void GenerateNode(const GRState *state); +}; +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngine.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngine.h new file mode 100644 index 0000000..ac407f6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -0,0 +1,465 @@ +//===-- GRExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- 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 meta-engine for path-sensitive dataflow analysis that +// is built on GRCoreEngine, but provides the boilerplate to execute transfer +// functions and build the ExplodedGraph at the expression level. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE +#define LLVM_CLANG_ANALYSIS_GREXPRENGINE + +#include "clang/Checker/PathSensitive/GRSubEngine.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRSimpleAPICheck.h" +#include "clang/Checker/PathSensitive/GRTransferFuncs.h" +#include "clang/Checker/BugReporter/BugReporter.h" +#include "clang/AST/Type.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" + +namespace clang { +class AnalysisManager; +class Checker; +class ObjCForCollectionStmt; + +class GRExprEngine : public GRSubEngine { + AnalysisManager &AMgr; + + GRCoreEngine CoreEngine; + + /// G - the simulation graph. + ExplodedGraph& G; + + /// Builder - The current GRStmtNodeBuilder which is used when building the + /// nodes for a given statement. + GRStmtNodeBuilder* Builder; + + /// StateMgr - Object that manages the data for all created states. + GRStateManager StateMgr; + + /// SymMgr - Object that manages the symbol information. + SymbolManager& SymMgr; + + /// ValMgr - Object that manages/creates SVals. + ValueManager &ValMgr; + + /// SVator - SValuator object that creates SVals from expressions. + SValuator &SVator; + + /// EntryNode - The immediate predecessor node. + ExplodedNode* EntryNode; + + /// CleanedState - The state for EntryNode "cleaned" of all dead + /// variables and symbols (as determined by a liveness analysis). + const GRState* CleanedState; + + /// CurrentStmt - The current block-level statement. + Stmt* CurrentStmt; + + // Obj-C Class Identifiers. + IdentifierInfo* NSExceptionII; + + // Obj-C Selectors. + Selector* NSExceptionInstanceRaiseSelectors; + Selector RaiseSel; + + llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor; + + typedef llvm::DenseMap<void *, unsigned> CheckerMap; + CheckerMap CheckerM; + + typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; + CheckersOrdered Checkers; + + /// BR - The BugReporter associated with this engine. It is important that + // this object be placed at the very end of member variables so that its + // destructor is called before the rest of the GRExprEngine is destroyed. + GRBugReporter BR; + + llvm::OwningPtr<GRTransferFuncs> TF; + + class CallExprWLItem { + public: + CallExpr::arg_iterator I; + ExplodedNode *N; + + CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n) + : I(i), N(n) {} + }; + +public: + GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf); + + ~GRExprEngine(); + + void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { + CoreEngine.ExecuteWorkList(L, Steps); + } + + /// getContext - Return the ASTContext associated with this analysis. + ASTContext& getContext() const { return G.getContext(); } + + AnalysisManager &getAnalysisManager() const { return AMgr; } + + SValuator &getSValuator() { return SVator; } + + GRTransferFuncs& getTF() { return *TF; } + + BugReporter& getBugReporter() { return BR; } + + GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } + + // FIXME: Remove once GRTransferFuncs is no longer referenced. + void setTransferFunction(GRTransferFuncs* tf); + + /// ViewGraph - Visualize the ExplodedGraph created by executing the + /// simulation. + void ViewGraph(bool trim = false); + + void ViewGraph(ExplodedNode** Beg, ExplodedNode** End); + + /// getInitialState - Return the initial state used for the root vertex + /// in the ExplodedGraph. + const GRState* getInitialState(const LocationContext *InitLoc); + + ExplodedGraph& getGraph() { return G; } + const ExplodedGraph& getGraph() const { return G; } + + template <typename CHECKER> + void registerCheck(CHECKER *check) { + unsigned entry = Checkers.size(); + void *tag = CHECKER::getTag(); + Checkers.push_back(std::make_pair(tag, check)); + CheckerM[tag] = entry; + } + + Checker *lookupChecker(void *tag) const; + + template <typename CHECKER> + CHECKER *getChecker() const { + return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); + } + + void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C); + void AddCheck(GRSimpleAPICheck* A); + + /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor + /// nodes by processing the 'effects' of a block-level statement. + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder); + + /// ProcessBlockEntrance - Called by GRCoreEngine when start processing + /// a CFGBlock. This method returns true if the analysis should continue + /// exploring the given path, and false otherwise. + bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, + GRBlockCounter BC); + + /// ProcessBranch - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a branch condition. + void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder); + + /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a computed goto jump. + void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder); + + /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a switch statement. + void ProcessSwitch(GRSwitchNodeBuilder& builder); + + /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path + /// nodes when the control reaches the end of a function. + void ProcessEndPath(GREndPathNodeBuilder& builder); + + // Generate the entry node of the callee. + void ProcessCallEnter(GRCallEnterNodeBuilder &builder); + + // Generate the first post callsite node. + void ProcessCallExit(GRCallExitNodeBuilder &builder); + + /// EvalAssume - Callback function invoked by the ConstraintManager when + /// making assumptions about state values. + const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); + + GRStateManager& getStateManager() { return StateMgr; } + const GRStateManager& getStateManager() const { return StateMgr; } + + StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } + + ConstraintManager& getConstraintManager() { + return StateMgr.getConstraintManager(); + } + + // FIXME: Remove when we migrate over to just using ValueManager. + BasicValueFactory& getBasicVals() { + return StateMgr.getBasicVals(); + } + const BasicValueFactory& getBasicVals() const { + return StateMgr.getBasicVals(); + } + + ValueManager &getValueManager() { return ValMgr; } + const ValueManager &getValueManager() const { return ValMgr; } + + // FIXME: Remove when we migrate over to just using ValueManager. + SymbolManager& getSymbolManager() { return SymMgr; } + const SymbolManager& getSymbolManager() const { return SymMgr; } + +protected: + const GRState* GetState(ExplodedNode* N) { + return N == EntryNode ? CleanedState : N->getState(); + } + +public: + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind, + const void *tag = 0); + + /// CheckerVisit - Dispatcher for performing checker-specific logic + /// at specific statements. + void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + bool isPrevisit); + + bool CheckerEvalCall(const CallExpr *CE, + ExplodedNodeSet &Dst, + ExplodedNode *Pred); + + void CheckerEvalNilReceiver(const ObjCMessageExpr *ME, + ExplodedNodeSet &Dst, + const GRState *state, + ExplodedNode *Pred); + + void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, + ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + SVal location, SVal val, bool isPrevisit); + + + /// Visit - Transfer function logic for all statements. Dispatches to + /// other functions that handle specific kinds of statements. + void Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is + /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its + /// storage location. Note that not all kinds of expressions has lvalue. + void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitArraySubscriptExpr - Transfer function for array accesses. + void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitAsmStmt - Transfer function logic for inline asm. + void VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + void VisitAsmStmtHelperOutputs(AsmStmt* A, + AsmStmt::outputs_iterator I, + AsmStmt::outputs_iterator E, + ExplodedNode* Pred, ExplodedNodeSet& Dst); + + void VisitAsmStmtHelperInputs(AsmStmt* A, + AsmStmt::inputs_iterator I, + AsmStmt::inputs_iterator E, + ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitBlockExpr - Transfer function logic for BlockExprs. + void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst); + + /// VisitBinaryOperator - Transfer function logic for binary operators. + void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + + /// VisitCall - Transfer function for function calls. + void VisitCall(CallExpr* CE, ExplodedNode* Pred, + CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitCast - Transfer function logic for all casts (implicit and explicit). + void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred, + ExplodedNodeSet &Dst, bool asLValue); + + /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. + void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs. + void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs. + void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitDeclStmt - Transfer function logic for DeclStmts. + void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose + void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + /// VisitCondInit - Transfer function for handling the initialization + /// of a condition variable in an IfStmt, SwitchStmt, etc. + void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred, + ExplodedNodeSet& Dst); + + void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + /// VisitLogicalExpr - Transfer function logic for '&&', '||' + void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + /// VisitMemberExpr - Transfer function for member expressions. + void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); + + /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs. + void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitObjCForCollectionStmt - Transfer function logic for + /// ObjCForCollectionStmt. + void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, + ExplodedNode* Pred, + ExplodedNodeSet& Dst, SVal ElementV); + + /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. + void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + /// VisitReturnStmt - Transfer function logic for return statements. + void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitOffsetOfExpr - Transfer function for offsetof. + void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + /// VisitSizeOfAlignOfExpr - Transfer function for sizeof. + void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, + ExplodedNodeSet& Dst); + + /// VisitUnaryOperator - Transfer function logic for unary operators. + void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + ExplodedNodeSet & Dst); + + void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + /// Create a C++ temporary object for an rvalue. + void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + /// Synthesize CXXThisRegion. + const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, + const StackFrameContext *SFC); + + /// Evaluate arguments with a work list algorithm. + void EvalArguments(ExprIterator AI, ExprIterator AE, + const FunctionProtoType *FnType, + ExplodedNode *Pred, ExplodedNodeSet &Dst); + + /// 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. + void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex); + + SVal EvalMinus(SVal X) { + return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X; + } + + SVal EvalComplement(SVal X) { + return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X; + } + +public: + + SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, + NonLoc L, NonLoc R, QualType T) { + return SVator.EvalBinOpNN(state, op, L, R, T); + } + + SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, + NonLoc L, SVal R, QualType T) { + return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; + } + + SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, + SVal LHS, SVal RHS, QualType T) { + return SVator.EvalBinOp(ST, Op, LHS, RHS, T); + } + +protected: + void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, + ExplodedNode* Pred, const GRState *state) { + assert (Builder && "GRStmtNodeBuilder must be defined."); + getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state); + } + + const GRState* MarkBranch(const GRState* St, Stmt* Terminator, + bool branchTaken); + + /// EvalBind - Handle the semantics of binding a value to a specific location. + /// This method is used by EvalStore, VisitDeclStmt, and others. + void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE, + Stmt* StoreE, ExplodedNode* Pred, + const GRState* St, SVal location, SVal Val, + bool atDeclInit = false); + +public: + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, const void *tag = 0, + QualType LoadTy = QualType()); + + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, + ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, + const void *tag = 0); +private: + void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, const void *tag, + QualType LoadTy); + + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, + const GRState* St, SVal location, + const void *tag, bool isLoad); + + bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h new file mode 100644 index 0000000..5503412 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h @@ -0,0 +1,76 @@ +//===-- GRExprEngineBuilders.h - "Builder" classes for GRExprEngine -*- 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 GRExprEngine objects and their related components. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS +#define LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS +#include "clang/Checker/PathSensitive/GRExprEngine.h" +#include "clang/Analysis/Support/SaveAndRestore.h" + +namespace clang { + +class GRStmtNodeBuilderRef { + ExplodedNodeSet &Dst; + GRStmtNodeBuilder &B; + GRExprEngine& Eng; + ExplodedNode* Pred; + const GRState* state; + const Stmt* stmt; + const unsigned OldSize; + const bool AutoCreateNode; + SaveAndRestore<bool> OldSink; + SaveAndRestore<const void*> OldTag; + SaveOr OldHasGen; + +private: + friend class GRExprEngine; + + GRStmtNodeBuilderRef(); // do not implement + void operator=(const GRStmtNodeBuilderRef&); // do not implement + + GRStmtNodeBuilderRef(ExplodedNodeSet &dst, + GRStmtNodeBuilder &builder, + GRExprEngine& eng, + ExplodedNode* pred, + const GRState *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), OldTag(B.Tag), OldHasGen(B.HasGeneratedNode) {} + +public: + + ~GRStmtNodeBuilderRef() { + // 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 GRState *getState() { return state; } + + GRStateManager& getStateManager() { + return Eng.getStateManager(); + } + + ExplodedNode* MakeNode(const GRState* state) { + return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state); + } +}; + +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h new file mode 100644 index 0000000..6d85e5f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h @@ -0,0 +1,31 @@ +// GRCheckAPI.h - Simple API checks based on GRAuditor ------------*- 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 interface for building simple, path-sensitive checks +// that are stateless and only emit warnings at errors that occur at +// CallExpr or ObjCMessageExpr. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS +#define LLVM_CLANG_ANALYSIS_GRAPICHECKS + +#include "clang/Checker/PathSensitive/GRAuditor.h" + +namespace clang { + +class GRSimpleAPICheck : public GRAuditor { +public: + GRSimpleAPICheck() {} + virtual ~GRSimpleAPICheck() {} +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRState.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRState.h new file mode 100644 index 0000000..25ba1f8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRState.h @@ -0,0 +1,750 @@ +//== GRState*h - Path-Sens. "State" for tracking valuues -----*- 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 SymbolRef, ExprBindKey, and GRState* +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H +#define LLVM_CLANG_ANALYSIS_VALUESTATE_H + +#include "clang/Checker/PathSensitive/ConstraintManager.h" +#include "clang/Checker/PathSensitive/Environment.h" +#include "clang/Checker/PathSensitive/Store.h" +#include "clang/Checker/PathSensitive/ValueManager.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/Support/Casting.h" + +namespace llvm { +class APSInt; +class BumpPtrAllocator; +class raw_ostream; +} + +namespace clang { +class ASTContext; +class GRStateManager; +class Checker; + +typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&, + GRSubEngine&); +typedef StoreManager* (*StoreManagerCreator)(GRStateManager&); + +//===----------------------------------------------------------------------===// +// GRStateTrait - Traits used by the Generic Data Map of a GRState. +//===----------------------------------------------------------------------===// + +template <typename T> struct GRStatePartialTrait; + +template <typename T> struct GRStateTrait { + typedef typename T::data_type data_type; + static inline void* GDMIndex() { return &T::TagInt; } + static inline void* MakeVoidPtr(data_type D) { return (void*) D; } + static inline data_type MakeData(void* const* P) { + return P ? (data_type) *P : (data_type) 0; + } +}; + +//===----------------------------------------------------------------------===// +// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to SVals. +//===----------------------------------------------------------------------===// + +class GRStateManager; + +/// GRState - This class encapsulates the actual data values for +/// for a "state" in our symbolic value tracking. It is intended to be +/// used as a functional object; that is once it is created and made +/// "persistent" in a FoldingSet its values will never change. +class GRState : public llvm::FoldingSetNode { +public: + typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy; + typedef llvm::ImmutableMap<void*, void*> GenericDataMap; + +private: + void operator=(const GRState& R) const; // Do not implement. + + friend class GRStateManager; + + GRStateManager *StateMgr; + Environment Env; + Store St; + GenericDataMap GDM; + +public: + + /// This ctor is used when creating the first GRState object. + GRState(GRStateManager *mgr, const Environment& env, + Store st, GenericDataMap gdm) + : StateMgr(mgr), + Env(env), + St(st), + GDM(gdm) {} + + /// Copy ctor - We must explicitly define this or else the "Next" ptr + /// in FoldingSetNode will also get copied. + GRState(const GRState& RHS) + : llvm::FoldingSetNode(), + StateMgr(RHS.StateMgr), + Env(RHS.Env), + St(RHS.St), + GDM(RHS.GDM) {} + + /// getStateManager - Return the GRStateManager associated with this state. + GRStateManager &getStateManager() const { + return *StateMgr; + } + + /// getEnvironment - Return the environment associated with this state. + /// The environment is the mapping from expressions to values. + const Environment& getEnvironment() const { return Env; } + + /// getStore - Return the store associated with this state. The store + /// is a mapping from locations to values. + Store getStore() const { return St; } + + void setStore(Store s) { St = s; } + + /// getGDM - Return the generic data map associated with this state. + GenericDataMap getGDM() const { return GDM; } + + void setGDM(GenericDataMap gdm) { GDM = gdm; } + + /// Profile - Profile the contents of a GRState object for use + /// in a FoldingSet. + static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) { + V->Env.Profile(ID); + ID.AddPointer(V->St); + V->GDM.Profile(ID); + } + + /// Profile - Used to profile the contents of this object for inclusion + /// in a FoldingSet. + void Profile(llvm::FoldingSetNodeID& ID) const { + Profile(ID, this); + } + + SVal LookupExpr(Expr* E) const { + return Env.LookupExpr(E); + } + + /// makeWithStore - Return a GRState with the same values as the current + /// state with the exception of using the specified Store. + const GRState *makeWithStore(Store store) const; + + BasicValueFactory &getBasicVals() const; + SymbolManager &getSymbolManager() const; + + //==---------------------------------------------------------------------==// + // Constraints on values. + //==---------------------------------------------------------------------==// + // + // Each GRState records constraints on symbolic values. These constraints + // are managed using the ConstraintManager associated with a GRStateManager. + // As constraints gradually accrue on symbolic values, added constraints + // may conflict and indicate that a state is infeasible (as no real values + // could satisfy all the constraints). This is the principal mechanism + // for modeling path-sensitivity in GRExprEngine/GRState. + // + // Various "Assume" methods form the interface for adding constraints to + // symbolic values. A call to "Assume" indicates an assumption being placed + // on one or symbolic values. Assume methods take the following inputs: + // + // (1) A GRState object representing the current state. + // + // (2) The assumed constraint (which is specific to a given "Assume" method). + // + // (3) A binary value "Assumption" that indicates whether the constraint is + // assumed to be true or false. + // + // The output of "Assume" are two values: + // + // (a) "isFeasible" is set to true or false to indicate whether or not + // the assumption is feasible. + // + // (b) A new GRState object with the added constraints. + // + // FIXME: (a) should probably disappear since it is redundant with (b). + // (i.e., (b) could just be set to NULL). + // + + const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const; + + std::pair<const GRState*, const GRState*> + Assume(DefinedOrUnknownSVal cond) const; + + const GRState *AssumeInBound(DefinedOrUnknownSVal idx, + DefinedOrUnknownSVal upperBound, + bool assumption) const; + + //==---------------------------------------------------------------------==// + // Utility methods for getting regions. + //==---------------------------------------------------------------------==// + + const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; + + //==---------------------------------------------------------------------==// + // Binding and retrieving values to/from the environment and symbolic store. + //==---------------------------------------------------------------------==// + + /// BindCompoundLiteral - Return the state that has the bindings currently + /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region + /// for the compound literal and 'BegInit' and 'EndInit' represent an + /// array of initializer values. + const GRState *bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, + SVal V) const; + + const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; + + const GRState *bindDecl(const VarRegion *VR, SVal V) const; + + const GRState *bindDeclWithNoInit(const VarRegion *VR) const; + + const GRState *bindLoc(Loc location, SVal V) const; + + const GRState *bindLoc(SVal location, SVal V) const; + + const GRState *unbindLoc(Loc LV) const; + + /// Get the lvalue for a variable reference. + SVal getLValue(const VarDecl *D, const LocationContext *LC) const; + + /// Get the lvalue for a StringLiteral. + SVal getLValue(const StringLiteral *literal) const; + + SVal getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const; + + /// Get the lvalue for an ivar reference. + SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; + + /// Get the lvalue for a field reference. + SVal getLValue(const FieldDecl *decl, SVal Base) const; + + /// Get the lvalue for an array index. + SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; + + const llvm::APSInt *getSymVal(SymbolRef sym) const; + + SVal getSVal(const Stmt* Ex) const; + + SVal getSValAsScalarOrLoc(const Stmt *Ex) const; + + SVal getSVal(Loc LV, QualType T = QualType()) const; + + SVal getSVal(const MemRegion* R) const; + + SVal getSValAsScalarOrLoc(const MemRegion *R) const; + + const llvm::APSInt *getSymVal(SymbolRef sym); + + bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; + + bool scanReachableSymbols(const SVal *I, const SVal *E, + SymbolVisitor &visitor) const; + + bool scanReachableSymbols(const MemRegion * const *I, + const MemRegion * const *E, + SymbolVisitor &visitor) const; + + template <typename CB> CB scanReachableSymbols(SVal val) const; + template <typename CB> CB scanReachableSymbols(const SVal *beg, + const SVal *end) const; + + template <typename CB> CB + scanReachableSymbols(const MemRegion * const *beg, + const MemRegion * const *end) const; + + //==---------------------------------------------------------------------==// + // Accessing the Generic Data Map (GDM). + //==---------------------------------------------------------------------==// + + void* const* FindGDM(void* K) const; + + template<typename T> + const GRState *add(typename GRStateTrait<T>::key_type K) const; + + template <typename T> + typename GRStateTrait<T>::data_type + get() const { + return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex())); + } + + template<typename T> + typename GRStateTrait<T>::lookup_type + get(typename GRStateTrait<T>::key_type key) const { + void* const* d = FindGDM(GRStateTrait<T>::GDMIndex()); + return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key); + } + + template <typename T> + typename GRStateTrait<T>::context_type get_context() const; + + + template<typename T> + const GRState *remove(typename GRStateTrait<T>::key_type K) const; + + template<typename T> + const GRState *remove(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::context_type C) const; + template <typename T> + const GRState *remove() const; + + template<typename T> + const GRState *set(typename GRStateTrait<T>::data_type D) const; + + template<typename T> + const GRState *set(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::value_type E) const; + + template<typename T> + const GRState *set(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::value_type E, + typename GRStateTrait<T>::context_type C) const; + + template<typename T> + bool contains(typename GRStateTrait<T>::key_type key) const { + void* const* d = FindGDM(GRStateTrait<T>::GDMIndex()); + return GRStateTrait<T>::Contains(GRStateTrait<T>::MakeData(d), key); + } + + // State pretty-printing. + class Printer { + public: + virtual ~Printer() {} + virtual void Print(llvm::raw_ostream& Out, const GRState* state, + const char* nl, const char* sep) = 0; + }; + + // Pretty-printing. + void print(llvm::raw_ostream& Out, CFG &C, const char *nl = "\n", + const char *sep = "") const; + + void printStdErr(CFG &C) const; + + void printDOT(llvm::raw_ostream& Out, CFG &C) const; +}; + +class GRStateSet { + typedef llvm::SmallPtrSet<const GRState*,5> ImplTy; + ImplTy Impl; +public: + GRStateSet() {} + + inline void Add(const GRState* 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 { + GRStateSet& S; + unsigned StartSize; + const GRState* St; + public: + AutoPopulate(GRStateSet& s, const GRState* st) + : S(s), StartSize(S.size()), St(st) {} + + ~AutoPopulate() { + if (StartSize == S.size()) + S.Add(St); + } + }; +}; + +//===----------------------------------------------------------------------===// +// GRStateManager - Factory object for GRStates. +//===----------------------------------------------------------------------===// + +class GRStateManager { + friend class GRState; + friend class GRExprEngine; // FIXME: Remove. +private: + EnvironmentManager EnvMgr; + llvm::OwningPtr<StoreManager> StoreMgr; + llvm::OwningPtr<ConstraintManager> ConstraintMgr; + + GRState::GenericDataMap::Factory GDMFactory; + + typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy; + GDMContextsTy GDMContexts; + + /// Printers - A set of printer objects used for pretty-printing a GRState. + /// GRStateManager owns these objects. + std::vector<GRState::Printer*> Printers; + + /// StateSet - FoldingSet containing all the states created for analyzing + /// a particular function. This is used to unique states. + llvm::FoldingSet<GRState> StateSet; + + /// ValueMgr - Object that manages the data for all created SVals. + ValueManager ValueMgr; + + /// Alloc - A BumpPtrAllocator to allocate states. + llvm::BumpPtrAllocator &Alloc; + +public: + GRStateManager(ASTContext& Ctx, + StoreManagerCreator CreateStoreManager, + ConstraintManagerCreator CreateConstraintManager, + llvm::BumpPtrAllocator& alloc, + GRSubEngine &subeng) + : EnvMgr(alloc), + GDMFactory(alloc), + ValueMgr(alloc, Ctx, *this), + Alloc(alloc) { + StoreMgr.reset((*CreateStoreManager)(*this)); + ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng)); + } + + ~GRStateManager(); + + const GRState *getInitialState(const LocationContext *InitLoc); + + ASTContext &getContext() { return ValueMgr.getContext(); } + const ASTContext &getContext() const { return ValueMgr.getContext(); } + + BasicValueFactory &getBasicVals() { + return ValueMgr.getBasicValueFactory(); + } + const BasicValueFactory& getBasicVals() const { + return ValueMgr.getBasicValueFactory(); + } + + SymbolManager &getSymbolManager() { + return ValueMgr.getSymbolManager(); + } + const SymbolManager &getSymbolManager() const { + return ValueMgr.getSymbolManager(); + } + + ValueManager &getValueManager() { return ValueMgr; } + const ValueManager &getValueManager() const { return ValueMgr; } + + llvm::BumpPtrAllocator& getAllocator() { return Alloc; } + + MemRegionManager& getRegionManager() { + return ValueMgr.getRegionManager(); + } + const MemRegionManager& getRegionManager() const { + return ValueMgr.getRegionManager(); + } + + StoreManager& getStoreManager() { return *StoreMgr; } + ConstraintManager& getConstraintManager() { return *ConstraintMgr; } + + const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, + const StackFrameContext *LCtx, + SymbolReaper& SymReaper); + +public: + + SVal ArrayToPointer(Loc Array) { + return StoreMgr->ArrayToPointer(Array); + } + + // Methods that manipulate the GDM. + const GRState* addGDM(const GRState* St, void* Key, void* Data); + const GRState *removeGDM(const GRState *state, void *Key); + + // Methods that query & manipulate the Store. + + void iterBindings(const GRState* state, StoreManager::BindingsHandler& F) { + StoreMgr->iterBindings(state->getStore(), F); + } + + const GRState* getPersistentState(GRState& Impl); + + bool isEqual(const GRState* state, const Expr* Ex, const llvm::APSInt& V); + bool isEqual(const GRState* state, const Expr* Ex, uint64_t); + + //==---------------------------------------------------------------------==// + // Generic Data Map methods. + //==---------------------------------------------------------------------==// + // + // GRStateManager and GRState support a "generic data map" that allows + // different clients of GRState objects to embed arbitrary data within a + // GRState object. The generic data map is essentially an immutable map + // from a "tag" (that acts as the "key" for a client) and opaque values. + // Tags/keys and values are simply void* values. The typical way that clients + // generate unique tags are by taking the address of a static variable. + // Clients are responsible for ensuring that data values referred to by a + // the data pointer are immutable (and thus are essentially purely functional + // data). + // + // The templated methods below use the GRStateTrait<T> class + // to resolve keys into the GDM and to return data values to clients. + // + + // Trait based GDM dispatch. + template <typename T> + const GRState* set(const GRState* st, typename GRStateTrait<T>::data_type D) { + return addGDM(st, GRStateTrait<T>::GDMIndex(), + GRStateTrait<T>::MakeVoidPtr(D)); + } + + template<typename T> + const GRState* set(const GRState* st, + typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::value_type V, + typename GRStateTrait<T>::context_type C) { + + return addGDM(st, GRStateTrait<T>::GDMIndex(), + GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C))); + } + + template <typename T> + const GRState* add(const GRState* st, + typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::context_type C) { + return addGDM(st, GRStateTrait<T>::GDMIndex(), + GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Add(st->get<T>(), K, C))); + } + + template <typename T> + const GRState* remove(const GRState* st, + typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::context_type C) { + + return addGDM(st, GRStateTrait<T>::GDMIndex(), + GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C))); + } + + template <typename T> + const GRState *remove(const GRState *st) { + return removeGDM(st, GRStateTrait<T>::GDMIndex()); + } + + void* FindGDMContext(void* index, + void* (*CreateContext)(llvm::BumpPtrAllocator&), + void (*DeleteContext)(void*)); + + template <typename T> + typename GRStateTrait<T>::context_type get_context() { + void* p = FindGDMContext(GRStateTrait<T>::GDMIndex(), + GRStateTrait<T>::CreateContext, + GRStateTrait<T>::DeleteContext); + + return GRStateTrait<T>::MakeContext(p); + } + + const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) { + return ConstraintMgr->getSymVal(St, sym); + } + + void EndPath(const GRState* St) { + ConstraintMgr->EndPath(St); + } +}; + + +//===----------------------------------------------------------------------===// +// Out-of-line method definitions for GRState. +//===----------------------------------------------------------------------===// + +inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) { + return getStateManager().getSymVal(this, sym); +} + +inline const VarRegion* GRState::getRegion(const VarDecl *D, + const LocationContext *LC) const { + return getStateManager().getRegionManager().getVarRegion(D, LC); +} + +inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond, + bool Assumption) const { + if (Cond.isUnknown()) + return this; + + return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond), + Assumption); +} + +inline std::pair<const GRState*, const GRState*> +GRState::Assume(DefinedOrUnknownSVal Cond) const { + if (Cond.isUnknown()) + return std::make_pair(this, this); + + return getStateManager().ConstraintMgr->AssumeDual(this, + cast<DefinedSVal>(Cond)); +} + +inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, + DefinedOrUnknownSVal UpperBound, + bool Assumption) const { + if (Idx.isUnknown() || UpperBound.isUnknown()) + return this; + + ConstraintManager &CM = *getStateManager().ConstraintMgr; + return CM.AssumeInBound(this, cast<DefinedSVal>(Idx), + cast<DefinedSVal>(UpperBound), Assumption); +} + +inline const GRState * +GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, SVal V) const { + Store new_store = + getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V); + return makeWithStore(new_store); +} + +inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { + Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal); + return makeWithStore(new_store); +} + +inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { + Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR); + return makeWithStore(new_store); +} + +inline const GRState *GRState::bindLoc(Loc LV, SVal V) const { + Store new_store = getStateManager().StoreMgr->Bind(St, LV, V); + return makeWithStore(new_store); +} + +inline const GRState *GRState::bindLoc(SVal LV, SVal V) const { + return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); +} + +inline SVal GRState::getLValue(const VarDecl* VD, + const LocationContext *LC) const { + return getStateManager().StoreMgr->getLValueVar(VD, LC); +} + +inline SVal GRState::getLValue(const StringLiteral *literal) const { + return getStateManager().StoreMgr->getLValueString(literal); +} + +inline SVal GRState::getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const { + return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); +} + +inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const { + return getStateManager().StoreMgr->getLValueIvar(D, Base); +} + +inline SVal GRState::getLValue(const FieldDecl* D, SVal Base) const { + return getStateManager().StoreMgr->getLValueField(D, Base); +} + +inline SVal GRState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ + return getStateManager().StoreMgr->getLValueElement(ElementType, Idx, Base); +} + +inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const { + return getStateManager().getSymVal(this, sym); +} + +inline SVal GRState::getSVal(const Stmt* Ex) const { + return Env.GetSVal(Ex, getStateManager().ValueMgr); +} + +inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const { + if (const Expr *Ex = dyn_cast<Expr>(S)) { + QualType T = Ex->getType(); + if (Loc::IsLocType(T) || T->isIntegerType()) + return getSVal(S); + } + + return UnknownVal(); +} + +inline SVal GRState::getSVal(Loc LV, QualType T) const { + return getStateManager().StoreMgr->Retrieve(St, LV, T); +} + +inline SVal GRState::getSVal(const MemRegion* R) const { + return getStateManager().StoreMgr->Retrieve(St, loc::MemRegionVal(R)); +} + +inline BasicValueFactory &GRState::getBasicVals() const { + return getStateManager().getBasicVals(); +} + +inline SymbolManager &GRState::getSymbolManager() const { + return getStateManager().getSymbolManager(); +} + +template<typename T> +const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const { + return getStateManager().add<T>(this, K, get_context<T>()); +} + +template <typename T> +typename GRStateTrait<T>::context_type GRState::get_context() const { + return getStateManager().get_context<T>(); +} + +template<typename T> +const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const { + return getStateManager().remove<T>(this, K, get_context<T>()); +} + +template<typename T> +const GRState *GRState::remove(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::context_type C) const { + return getStateManager().remove<T>(this, K, C); +} + +template <typename T> +const GRState *GRState::remove() const { + return getStateManager().remove<T>(this); +} + +template<typename T> +const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const { + return getStateManager().set<T>(this, D); +} + +template<typename T> +const GRState *GRState::set(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::value_type E) const { + return getStateManager().set<T>(this, K, E, get_context<T>()); +} + +template<typename T> +const GRState *GRState::set(typename GRStateTrait<T>::key_type K, + typename GRStateTrait<T>::value_type E, + typename GRStateTrait<T>::context_type C) const { + return getStateManager().set<T>(this, K, E, C); +} + +template <typename CB> +CB GRState::scanReachableSymbols(SVal val) const { + CB cb(this); + scanReachableSymbols(val, cb); + return cb; +} + +template <typename CB> +CB GRState::scanReachableSymbols(const SVal *beg, const SVal *end) const { + CB cb(this); + scanReachableSymbols(beg, end, cb); + return cb; +} + +template <typename CB> +CB GRState::scanReachableSymbols(const MemRegion * const *beg, + const MemRegion * const *end) const { + CB cb(this); + scanReachableSymbols(beg, end, cb); + return cb; +} +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRStateTrait.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRStateTrait.h new file mode 100644 index 0000000..5189a1f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRStateTrait.h @@ -0,0 +1,148 @@ +//==- GRStateTrait.h - Partial implementations of GRStateTrait -----*- 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 partial implementations of template specializations of +// the class GRStateTrait<>. GRStateTrait<> is used by GRState to implement +// set/get methods for mapulating a GRState's generic data map. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H +#define LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H + +namespace llvm { + class BumpPtrAllocator; + template <typename K, typename D, typename I> class ImmutableMap; + template <typename K, typename I> class ImmutableSet; + template <typename T> class ImmutableList; + template <typename T> class ImmutableListImpl; +} + +namespace clang { + template <typename T> struct GRStatePartialTrait; + + // Partial-specialization for ImmutableMap. + + template <typename Key, typename Data, typename Info> + struct GRStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { + typedef llvm::ImmutableMap<Key,Data,Info> data_type; + typedef typename data_type::Factory& context_type; + typedef Key key_type; + typedef Data value_type; + typedef const value_type* lookup_type; + + static inline data_type MakeData(void* const* p) { + return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); + } + static inline void* MakeVoidPtr(data_type B) { + return B.getRoot(); + } + static lookup_type Lookup(data_type B, key_type K) { + return B.lookup(K); + } + static data_type Set(data_type B, key_type K, value_type E,context_type F){ + return F.Add(B, K, E); + } + + static data_type Remove(data_type B, key_type K, context_type F) { + return F.Remove(B, K); + } + + static inline context_type MakeContext(void* p) { + return *((typename data_type::Factory*) p); + } + + static void* CreateContext(llvm::BumpPtrAllocator& Alloc) { + return new typename data_type::Factory(Alloc); + } + + static void DeleteContext(void* Ctx) { + delete (typename data_type::Factory*) Ctx; + } + }; + + + // Partial-specialization for ImmutableSet. + + template <typename Key, typename Info> + struct GRStatePartialTrait< llvm::ImmutableSet<Key,Info> > { + typedef llvm::ImmutableSet<Key,Info> data_type; + typedef typename data_type::Factory& context_type; + typedef Key key_type; + + static inline data_type MakeData(void* const* p) { + return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); + } + + static inline void* MakeVoidPtr(data_type B) { + return B.getRoot(); + } + + static data_type Add(data_type B, key_type K, context_type F) { + return F.Add(B, K); + } + + static data_type Remove(data_type B, key_type K, context_type F) { + return F.Remove(B, K); + } + + static bool Contains(data_type B, key_type K) { + return B.contains(K); + } + + static inline context_type MakeContext(void* p) { + return *((typename data_type::Factory*) p); + } + + static void* CreateContext(llvm::BumpPtrAllocator& Alloc) { + return new typename data_type::Factory(Alloc); + } + + static void DeleteContext(void* Ctx) { + delete (typename data_type::Factory*) Ctx; + } + }; + + // Partial-specialization for ImmutableList. + + template <typename T> + struct GRStatePartialTrait< llvm::ImmutableList<T> > { + typedef llvm::ImmutableList<T> data_type; + typedef T key_type; + typedef typename data_type::Factory& context_type; + + static data_type Add(data_type L, key_type K, context_type F) { + return F.Add(K, L); + } + + static inline data_type MakeData(void* const* p) { + return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) + : data_type(0); + } + + static inline void* MakeVoidPtr(data_type D) { + return (void*) D.getInternalPointer(); + } + + static inline context_type MakeContext(void* p) { + return *((typename data_type::Factory*) p); + } + + static void* CreateContext(llvm::BumpPtrAllocator& Alloc) { + return new typename data_type::Factory(Alloc); + } + + static void DeleteContext(void* Ctx) { + delete (typename data_type::Factory*) Ctx; + } + }; +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSubEngine.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSubEngine.h new file mode 100644 index 0000000..d2e7457 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -0,0 +1,84 @@ +//== GRSubEngine.h - Interface of the subengine of GRCoreEngine ----*- 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 interface of a subengine of the GRCoreEngine. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H +#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H + +#include "clang/Checker/PathSensitive/SVals.h" + +namespace clang { + +class Stmt; +class CFGBlock; +class CFGElement; +class ExplodedNode; +class GRState; +class GRStateManager; +class GRBlockCounter; +class GRStmtNodeBuilder; +class GRBranchNodeBuilder; +class GRIndirectGotoNodeBuilder; +class GRSwitchNodeBuilder; +class GREndPathNodeBuilder; +class GRCallEnterNodeBuilder; +class GRCallExitNodeBuilder; +class LocationContext; + +class GRSubEngine { +public: + virtual ~GRSubEngine() {} + + virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0; + + virtual GRStateManager& getStateManager() = 0; + + /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor + /// nodes by processing the 'effects' of a block-level statement. + virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; + + /// ProcessBlockEntrance - Called by GRCoreEngine when start processing + /// a CFGBlock. This method returns true if the analysis should continue + /// exploring the given path, and false otherwise. + virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, + GRBlockCounter BC) = 0; + + /// ProcessBranch - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a branch condition. + virtual void ProcessBranch(Stmt* Condition, Stmt* Term, + GRBranchNodeBuilder& builder) = 0; + + /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a computed goto jump. + virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) = 0; + + /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a switch statement. + virtual void ProcessSwitch(GRSwitchNodeBuilder& builder) = 0; + + /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path + /// nodes when the control reaches the end of a function. + virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0; + + // Generate the entry node of the callee. + virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0; + + // Generate the first post callsite node. + virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; + + /// EvalAssume - Called by ConstraintManager. Used to call checker-specific + /// logic for handling assumptions on symbolic values. + virtual const GRState* ProcessAssume(const GRState *state, + SVal cond, bool assumption) = 0; +}; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRTransferFuncs.h new file mode 100644 index 0000000..13325ed --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -0,0 +1,87 @@ +//== GRTransferFuncs.h - Path-Sens. Transfer Functions Interface -*- 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 GRTransferFuncs, which provides a base-class that +// defines an interface for transfer functions used by GRExprEngine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRTF +#define LLVM_CLANG_ANALYSIS_GRTF + +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include <vector> + +namespace clang { +class ExplodedNode; +class ExplodedNodeSet; +class GREndPathNodeBuilder; +class GRExprEngine; +class GRStmtNodeBuilder; +class GRStmtNodeBuilderRef; +class ObjCMessageExpr; + +class GRTransferFuncs { +public: + GRTransferFuncs() {} + virtual ~GRTransferFuncs() {} + + virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {} + virtual void RegisterChecks(GRExprEngine& Eng) {} + + + // Calls. + + virtual void EvalCall(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + CallExpr* CE, SVal L, + ExplodedNode* Pred) {} + + virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + ObjCMessageExpr* ME, + ExplodedNode* Pred, + const GRState *state) {} + + // Stores. + + virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {} + + // End-of-path and dead symbol notification. + + virtual void EvalEndPath(GRExprEngine& Engine, + GREndPathNodeBuilder& Builder) {} + + + virtual void EvalDeadSymbols(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + ExplodedNode* Pred, + Stmt* S, const GRState* state, + SymbolReaper& SymReaper) {} + + // Return statements. + virtual void EvalReturn(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + ReturnStmt* S, + ExplodedNode* Pred) {} + + // Assumptions. + virtual const GRState* EvalAssume(const GRState *state, + SVal Cond, bool Assumption) { + return state; + } +}; +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRWorkList.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRWorkList.h new file mode 100644 index 0000000..b8f90fa --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/GRWorkList.h @@ -0,0 +1,79 @@ +//==- GRWorkList.h - Worklist class used by GRCoreEngine -----------*- 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 GRWorkList, a pure virtual class that represents an opaque +// worklist used by GRCoreEngine to explore the reachability state space. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST +#define LLVM_CLANG_ANALYSIS_GRWORKLIST + +#include "clang/Checker/PathSensitive/GRBlockCounter.h" +#include <cstddef> + +namespace clang { + +class CFGBlock; +class ExplodedNode; +class ExplodedNodeImpl; + +class GRWorkListUnit { + ExplodedNode* Node; + GRBlockCounter Counter; + CFGBlock* Block; + unsigned BlockIdx; // This is the index of the next statement. + +public: + GRWorkListUnit(ExplodedNode* N, GRBlockCounter C, + CFGBlock* B, unsigned idx) + : Node(N), + Counter(C), + Block(B), + BlockIdx(idx) {} + + explicit GRWorkListUnit(ExplodedNode* N, GRBlockCounter C) + : Node(N), + Counter(C), + Block(NULL), + BlockIdx(0) {} + + ExplodedNode* getNode() const { return Node; } + GRBlockCounter getBlockCounter() const { return Counter; } + CFGBlock* getBlock() const { return Block; } + unsigned getIndex() const { return BlockIdx; } +}; + +class GRWorkList { + GRBlockCounter CurrentCounter; +public: + virtual ~GRWorkList(); + virtual bool hasWork() const = 0; + + virtual void Enqueue(const GRWorkListUnit& U) = 0; + + void Enqueue(ExplodedNode* N, CFGBlock& B, unsigned idx) { + Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx)); + } + + void Enqueue(ExplodedNode* N) { + Enqueue(GRWorkListUnit(N, CurrentCounter)); + } + + virtual GRWorkListUnit Dequeue() = 0; + + void setBlockCounter(GRBlockCounter C) { CurrentCounter = C; } + GRBlockCounter getBlockCounter() const { return CurrentCounter; } + + static GRWorkList *MakeDFS(); + static GRWorkList *MakeBFS(); + static GRWorkList *MakeBFSBlockDFSContents(); +}; +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/MemRegion.h new file mode 100644 index 0000000..2ab3b42 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/MemRegion.h @@ -0,0 +1,967 @@ +//== MemRegion.h - Abstract memory regions for static analysis --*- 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 MemRegion and its subclasses. MemRegion defines a +// partially-typed abstraction of memory useful for path-sensitive dataflow +// analyses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H +#define LLVM_CLANG_ANALYSIS_MEMREGION_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "llvm/Support/Casting.h" +#include "llvm/ADT/FoldingSet.h" +#include <string> + +namespace llvm { +class BumpPtrAllocator; +class raw_ostream; +} + +namespace clang { + +class MemRegionManager; +class MemSpaceRegion; +class LocationContext; +class StackFrameContext; +class VarRegion; + +//===----------------------------------------------------------------------===// +// Base region classes. +//===----------------------------------------------------------------------===// + +/// MemRegion - The root abstract class for all memory regions. +class MemRegion : public llvm::FoldingSetNode { + friend class MemRegionManager; +public: + enum Kind { + // Memory spaces. + BEG_MEMSPACES, + GenericMemSpaceRegionKind = BEG_MEMSPACES, + StackLocalsSpaceRegionKind, + StackArgumentsSpaceRegionKind, + HeapSpaceRegionKind, + UnknownSpaceRegionKind, + GlobalsSpaceRegionKind, + END_MEMSPACES = GlobalsSpaceRegionKind, + // Untyped regions. + SymbolicRegionKind, + AllocaRegionKind, + // Typed regions. + BEG_TYPED_REGIONS, + FunctionTextRegionKind = BEG_TYPED_REGIONS, + BlockTextRegionKind, + BlockDataRegionKind, + CompoundLiteralRegionKind, + CXXThisRegionKind, + StringRegionKind, + ElementRegionKind, + // Decl Regions. + BEG_DECL_REGIONS, + VarRegionKind = BEG_DECL_REGIONS, + FieldRegionKind, + ObjCIvarRegionKind, + CXXObjectRegionKind, + END_DECL_REGIONS = CXXObjectRegionKind, + END_TYPED_REGIONS = END_DECL_REGIONS + }; + +private: + const Kind kind; + +protected: + MemRegion(Kind k) : kind(k) {} + virtual ~MemRegion(); + +public: + ASTContext &getContext() const; + + virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0; + + virtual MemRegionManager* getMemRegionManager() const = 0; + + std::string getString() const; + + const MemSpaceRegion *getMemorySpace() const; + + const MemRegion *getBaseRegion() const; + + const MemRegion *StripCasts() const; + + bool hasGlobalsOrParametersStorage() const; + + bool hasStackStorage() const; + + bool hasStackNonParametersStorage() const; + + bool hasStackParametersStorage() const; + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void dump() const; + + Kind getKind() const { return kind; } + + template<typename RegionTy> const RegionTy* getAs() const; + + virtual bool isBoundable() const { return false; } + + static bool classof(const MemRegion*) { return true; } +}; + +/// MemSpaceRegion - A memory region that represents and "memory space"; +/// for example, the set of global variables, the stack frame, etc. +class MemSpaceRegion : public MemRegion { +protected: + friend class MemRegionManager; + + MemRegionManager *Mgr; + + MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) + : MemRegion(k), Mgr(mgr) { + assert(classof(this)); + } + + MemRegionManager* getMemRegionManager() const { return Mgr; } + +public: + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= BEG_MEMSPACES && k <= END_MEMSPACES; + } +}; + +class GlobalsSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + GlobalsSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalsSpaceRegionKind; + } +}; + +class HeapSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + HeapSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == HeapSpaceRegionKind; + } +}; + +class UnknownSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + UnknownSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == UnknownSpaceRegionKind; + } +}; + +class StackSpaceRegion : public MemSpaceRegion { +private: + const StackFrameContext *SFC; + +protected: + StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) + : MemSpaceRegion(mgr, k), SFC(sfc) { + assert(classof(this)); + } + +public: + const StackFrameContext *getStackFrame() const { return SFC; } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= StackLocalsSpaceRegionKind && + k <= StackArgumentsSpaceRegionKind; + } +}; + +class StackLocalsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackLocalsSpaceRegionKind; + } +}; + +class StackArgumentsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackArgumentsSpaceRegionKind; + } +}; + +/// SubRegion - A region that subsets another larger region. Most regions +/// are subclasses of SubRegion. +class SubRegion : public MemRegion { +protected: + const MemRegion* superRegion; + SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {} +public: + const MemRegion* getSuperRegion() const { + return superRegion; + } + + MemRegionManager* getMemRegionManager() const; + + bool isSubRegionOf(const MemRegion* R) const; + + static bool classof(const MemRegion* R) { + return R->getKind() > END_MEMSPACES; + } +}; + +//===----------------------------------------------------------------------===// +// Auxillary data classes for use with MemRegions. +//===----------------------------------------------------------------------===// + +class ElementRegion; + +class RegionRawOffset { +private: + friend class ElementRegion; + + const MemRegion *Region; + int64_t Offset; + + RegionRawOffset(const MemRegion* reg, int64_t offset = 0) + : Region(reg), Offset(offset) {} + +public: + // FIXME: Eventually support symbolic offsets. + int64_t getByteOffset() const { return Offset; } + const MemRegion *getRegion() const { return Region; } + + void dumpToStream(llvm::raw_ostream& os) const; + void dump() const; +}; + +//===----------------------------------------------------------------------===// +// MemRegion subclasses. +//===----------------------------------------------------------------------===// + +/// AllocaRegion - A region that represents an untyped blob of bytes created +/// by a call to 'alloca'. +class AllocaRegion : public SubRegion { + friend class MemRegionManager; +protected: + unsigned Cnt; // Block counter. Used to distinguish different pieces of + // memory allocated by alloca at the same call site. + const Expr* Ex; + + AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion *superRegion) + : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {} + +public: + + const Expr* getExpr() const { return Ex; } + + bool isBoundable() const { return true; } + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex, + unsigned Cnt, const MemRegion *superRegion); + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == AllocaRegionKind; + } +}; + +/// TypedRegion - An abstract class representing regions that are typed. +class TypedRegion : public SubRegion { +protected: + TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} + +public: + virtual QualType getValueType(ASTContext &C) const = 0; + + virtual QualType getLocationType(ASTContext& C) const { + // FIXME: We can possibly optimize this later to cache this value. + return C.getPointerType(getValueType(C)); + } + + QualType getDesugaredValueType(ASTContext& C) const { + QualType T = getValueType(C); + return T.getTypePtr() ? T.getDesugaredType() : T; + } + + QualType getDesugaredLocationType(ASTContext& C) const { + return getLocationType(C).getDesugaredType(); + } + + bool isBoundable() const { + return !getValueType(getContext()).isNull(); + } + + static bool classof(const MemRegion* R) { + unsigned k = R->getKind(); + return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS; + } +}; + + +class CodeTextRegion : public TypedRegion { +protected: + CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} +public: + QualType getValueType(ASTContext &C) const { + // Do not get the object type of a CodeTextRegion. + assert(0); + return QualType(); + } + + bool isBoundable() const { return false; } + + static bool classof(const MemRegion* R) { + Kind k = R->getKind(); + return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; + } +}; + +/// FunctionTextRegion - A region that represents code texts of function. +class FunctionTextRegion : public CodeTextRegion { + const FunctionDecl *FD; +public: + FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} + + QualType getLocationType(ASTContext &C) const { + return C.getPointerType(FD->getType()); + } + + const FunctionDecl *getDecl() const { + return FD; + } + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD, + const MemRegion*); + + static bool classof(const MemRegion* R) { + return R->getKind() == FunctionTextRegionKind; + } +}; + + +/// BlockTextRegion - A region that represents code texts of blocks (closures). +/// Blocks are represented with two kinds of regions. BlockTextRegions +/// represent the "code", while BlockDataRegions represent instances of blocks, +/// which correspond to "code+data". The distinction is important, because +/// like a closure a block captures the values of externally referenced +/// variables. +class BlockTextRegion : public CodeTextRegion { + friend class MemRegionManager; + + const BlockDecl *BD; + AnalysisContext *AC; + CanQualType locTy; + + BlockTextRegion(const BlockDecl *bd, CanQualType lTy, + AnalysisContext *ac, const MemRegion* sreg) + : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} + +public: + QualType getLocationType(ASTContext &C) const { + return locTy; + } + + const BlockDecl *getDecl() const { + return BD; + } + + AnalysisContext *getAnalysisContext() const { return AC; } + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, + CanQualType, const AnalysisContext*, + const MemRegion*); + + static bool classof(const MemRegion* R) { + return R->getKind() == BlockTextRegionKind; + } +}; + +/// BlockDataRegion - A region that represents a block instance. +/// Blocks are represented with two kinds of regions. BlockTextRegions +/// represent the "code", while BlockDataRegions represent instances of blocks, +/// which correspond to "code+data". The distinction is important, because +/// like a closure a block captures the values of externally referenced +/// variables. +class BlockDataRegion : public SubRegion { + friend class MemRegionManager; + const BlockTextRegion *BC; + const LocationContext *LC; // Can be null */ + void *ReferencedVars; + + BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, + const MemRegion *sreg) + : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} + +public: + const BlockTextRegion *getCodeRegion() const { return BC; } + + const BlockDecl *getDecl() const { return BC->getDecl(); } + + class referenced_vars_iterator { + const MemRegion * const *R; + public: + explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {} + + operator const MemRegion * const *() const { + return R; + } + + const VarRegion* operator*() const { + return cast<VarRegion>(*R); + } + + bool operator==(const referenced_vars_iterator &I) const { + return I.R == R; + } + bool operator!=(const referenced_vars_iterator &I) const { + return I.R != R; + } + referenced_vars_iterator& operator++() { + ++R; + return *this; + } + }; + + referenced_vars_iterator referenced_vars_begin() const; + referenced_vars_iterator referenced_vars_end() const; + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, + const LocationContext *, const MemRegion *); + + static bool classof(const MemRegion* R) { + return R->getKind() == BlockDataRegionKind; + } +private: + void LazyInitializeReferencedVars(); +}; + +/// SymbolicRegion - A special, "non-concrete" region. Unlike other region +/// clases, SymbolicRegion represents a region that serves as an alias for +/// either a real region, a NULL pointer, etc. It essentially is used to +/// map the concept of symbolic values into the domain of regions. Symbolic +/// regions do not need to be typed. +class SymbolicRegion : public SubRegion { +protected: + const SymbolRef sym; + +public: + SymbolicRegion(const SymbolRef s, const MemRegion* sreg) + : SubRegion(sreg, SymbolicRegionKind), sym(s) {} + + SymbolRef getSymbol() const { + return sym; + } + + bool isBoundable() const { return true; } + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + SymbolRef sym, + const MemRegion* superRegion); + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == SymbolicRegionKind; + } +}; + +/// StringRegion - Region associated with a StringLiteral. +class StringRegion : public TypedRegion { + friend class MemRegionManager; + const StringLiteral* Str; +protected: + + StringRegion(const StringLiteral* str, const MemRegion* sreg) + : TypedRegion(sreg, StringRegionKind), Str(str) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const StringLiteral* Str, + const MemRegion* superRegion); + +public: + + const StringLiteral* getStringLiteral() const { return Str; } + + QualType getValueType(ASTContext& C) const { + return Str->getType(); + } + + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ProfileRegion(ID, Str, superRegion); + } + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == StringRegionKind; + } +}; + +/// CompoundLiteralRegion - A memory region representing a compound literal. +/// Compound literals are essentially temporaries that are stack allocated +/// or in the global constant pool. +class CompoundLiteralRegion : public TypedRegion { +private: + friend class MemRegionManager; + const CompoundLiteralExpr* CL; + + CompoundLiteralRegion(const CompoundLiteralExpr* cl, const MemRegion* sReg) + : TypedRegion(sReg, CompoundLiteralRegionKind), CL(cl) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const CompoundLiteralExpr* CL, + const MemRegion* superRegion); +public: + QualType getValueType(ASTContext& C) const { + return C.getCanonicalType(CL->getType()); + } + + bool isBoundable() const { return !CL->isFileScope(); } + + void Profile(llvm::FoldingSetNodeID& ID) const; + + void dumpToStream(llvm::raw_ostream& os) const; + + const CompoundLiteralExpr* getLiteralExpr() const { return CL; } + + static bool classof(const MemRegion* R) { + return R->getKind() == CompoundLiteralRegionKind; + } +}; + +class DeclRegion : public TypedRegion { +protected: + const Decl* D; + + DeclRegion(const Decl* d, const MemRegion* sReg, Kind k) + : TypedRegion(sReg, k), D(d) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D, + const MemRegion* superRegion, Kind k); + +public: + const Decl* getDecl() const { return D; } + void Profile(llvm::FoldingSetNodeID& ID) const; + + static bool classof(const MemRegion* R) { + unsigned k = R->getKind(); + return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; + } +}; + +class VarRegion : public DeclRegion { + friend class MemRegionManager; + + // Constructors and private methods. + VarRegion(const VarDecl* vd, const MemRegion* sReg) + : DeclRegion(vd, sReg, VarRegionKind) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD, + const MemRegion *superRegion) { + DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); + } + + void Profile(llvm::FoldingSetNodeID& ID) const; + +public: + const VarDecl *getDecl() const { return cast<VarDecl>(D); } + + const StackFrameContext *getStackFrame() const; + + QualType getValueType(ASTContext& C) const { + // FIXME: We can cache this if needed. + return C.getCanonicalType(getDecl()->getType()); + } + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == VarRegionKind; + } +}; + +/// CXXThisRegion - Represents the region for the implicit 'this' parameter +/// in a call to a C++ method. This region doesn't represent the object +/// referred to by 'this', but rather 'this' itself. +class CXXThisRegion : public TypedRegion { + friend class MemRegionManager; + CXXThisRegion(const PointerType *thisPointerTy, + const MemRegion *sReg) + : TypedRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + const PointerType *PT, + const MemRegion *sReg); + + void Profile(llvm::FoldingSetNodeID &ID) const; + +public: + QualType getValueType(ASTContext &C) const { + return QualType(ThisPointerTy, 0); + } + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == CXXThisRegionKind; + } + +private: + const PointerType *ThisPointerTy; +}; + +class FieldRegion : public DeclRegion { + friend class MemRegionManager; + + FieldRegion(const FieldDecl* fd, const MemRegion* sReg) + : DeclRegion(fd, sReg, FieldRegionKind) {} + +public: + + void dumpToStream(llvm::raw_ostream& os) const; + + const FieldDecl* getDecl() const { return cast<FieldDecl>(D); } + + QualType getValueType(ASTContext& C) const { + // FIXME: We can cache this if needed. + return C.getCanonicalType(getDecl()->getType()); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD, + const MemRegion* superRegion) { + DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); + } + + static bool classof(const MemRegion* R) { + return R->getKind() == FieldRegionKind; + } +}; + +class ObjCIvarRegion : public DeclRegion { + + friend class MemRegionManager; + + ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg) + : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {} + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl* ivd, + const MemRegion* superRegion) { + DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind); + } + +public: + const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); } + QualType getValueType(ASTContext&) const { return getDecl()->getType(); } + + void dumpToStream(llvm::raw_ostream& os) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == ObjCIvarRegionKind; + } +}; + +class ElementRegion : public TypedRegion { + friend class MemRegionManager; + + QualType ElementType; + SVal Index; + + ElementRegion(QualType elementType, SVal Idx, const MemRegion* sReg) + : TypedRegion(sReg, ElementRegionKind), + ElementType(elementType), Index(Idx) { + assert((!isa<nonloc::ConcreteInt>(&Idx) || + cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) && + "The index must be signed"); + } + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType, + SVal Idx, const MemRegion* superRegion); + +public: + + SVal getIndex() const { return Index; } + + QualType getValueType(ASTContext&) const { + return ElementType; + } + + QualType getElementType() const { + return ElementType; + } + + RegionRawOffset getAsRawOffset() const; + + void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == ElementRegionKind; + } +}; + +// C++ temporary object associated with an expression. +class CXXObjectRegion : public TypedRegion { + friend class MemRegionManager; + + Expr const *Ex; + + CXXObjectRegion(Expr const *E, MemRegion const *sReg) + : TypedRegion(sReg, CXXObjectRegionKind), Ex(E) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + Expr const *E, const MemRegion *sReg); + +public: + QualType getValueType(ASTContext& C) const { + return Ex->getType(); + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == CXXObjectRegionKind; + } +}; + +template<typename RegionTy> +const RegionTy* MemRegion::getAs() const { + if (const RegionTy* RT = dyn_cast<RegionTy>(this)) + return RT; + + return NULL; +} + +//===----------------------------------------------------------------------===// +// MemRegionManager - Factory object for creating regions. +//===----------------------------------------------------------------------===// + +class MemRegionManager { + ASTContext &C; + llvm::BumpPtrAllocator& A; + llvm::FoldingSet<MemRegion> Regions; + + GlobalsSpaceRegion *globals; + + llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> + StackLocalsSpaceRegions; + llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> + StackArgumentsSpaceRegions; + + HeapSpaceRegion *heap; + UnknownSpaceRegion *unknown; + MemSpaceRegion *code; + +public: + MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) + : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {} + + ~MemRegionManager(); + + ASTContext &getContext() { return C; } + + llvm::BumpPtrAllocator &getAllocator() { return A; } + + /// getStackLocalsRegion - Retrieve the memory region associated with the + /// specified stack frame. + const StackLocalsSpaceRegion * + getStackLocalsRegion(const StackFrameContext *STC); + + /// getStackArgumentsRegion - Retrieve the memory region associated with + /// function/method arguments of the specified stack frame. + const StackArgumentsSpaceRegion * + getStackArgumentsRegion(const StackFrameContext *STC); + + /// getGlobalsRegion - Retrieve the memory region associated with + /// all global variables. + const GlobalsSpaceRegion *getGlobalsRegion(); + + /// getHeapRegion - Retrieve the memory region associated with the + /// generic "heap". + const HeapSpaceRegion *getHeapRegion(); + + /// getUnknownRegion - Retrieve the memory region associated with unknown + /// memory space. + const MemSpaceRegion *getUnknownRegion(); + + const MemSpaceRegion *getCodeRegion(); + + /// getAllocaRegion - Retrieve a region associated with a call to alloca(). + const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt, + const LocationContext *LC); + + /// getCompoundLiteralRegion - Retrieve the region associated with a + /// given CompoundLiteral. + const CompoundLiteralRegion* + getCompoundLiteralRegion(const CompoundLiteralExpr* CL, + const LocationContext *LC); + + /// getCXXThisRegion - Retrieve the [artifical] region associated with the + /// parameter 'this'. + const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, + const LocationContext *LC); + + /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. + const SymbolicRegion* getSymbolicRegion(SymbolRef sym); + + const StringRegion* getStringRegion(const StringLiteral* Str); + + /// getVarRegion - Retrieve or create the memory region associated with + /// a specified VarDecl and LocationContext. + const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); + + /// getVarRegion - Retrieve or create the memory region associated with + /// a specified VarDecl and super region. + const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); + + /// getElementRegion - Retrieve the memory region associated with the + /// associated element type, index, and super region. + const ElementRegion *getElementRegion(QualType elementType, SVal Idx, + const MemRegion *superRegion, + ASTContext &Ctx); + + const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, + const MemRegion *superRegion) { + return getElementRegion(ER->getElementType(), ER->getIndex(), + superRegion, ER->getContext()); + } + + /// getFieldRegion - Retrieve or create the memory region associated with + /// a specified FieldDecl. 'superRegion' corresponds to the containing + /// memory region (which typically represents the memory representing + /// a structure or class). + const FieldRegion *getFieldRegion(const FieldDecl* fd, + const MemRegion* superRegion); + + const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, + const MemRegion *superRegion) { + return getFieldRegion(FR->getDecl(), superRegion); + } + + /// getObjCIvarRegion - Retrieve or create the memory region associated with + /// a specified Objective-c instance variable. 'superRegion' corresponds + /// to the containing region (which typically represents the Objective-C + /// object). + const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, + const MemRegion* superRegion); + + const CXXObjectRegion *getCXXObjectRegion(Expr const *Ex, + LocationContext const *LC); + + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, + CanQualType locTy, + AnalysisContext *AC); + + /// getBlockDataRegion - Get the memory region associated with an instance + /// of a block. Unlike many other MemRegions, the LocationContext* + /// argument is allowed to be NULL for cases where we have no known + /// context. + 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); + + template <typename RegionTy, typename A1> + RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion); + + template <typename RegionTy, typename A1, typename A2> + RegionTy* getRegion(const A1 a1, const A2 a2); + + template <typename RegionTy, typename A1, typename A2> + RegionTy* getSubRegion(const A1 a1, const A2 a2, + const MemRegion* superRegion); + + template <typename RegionTy, typename A1, typename A2, typename A3> + RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, + const MemRegion* superRegion); + + template <typename REG> + const REG* LazyAllocate(REG*& region); + + template <typename REG, typename ARG> + const REG* LazyAllocate(REG*& region, ARG a); +}; + +//===----------------------------------------------------------------------===// +// Out-of-line member definitions. +//===----------------------------------------------------------------------===// + +inline ASTContext& MemRegion::getContext() const { + return getMemRegionManager()->getContext(); +} + +} // end clang namespace + +//===----------------------------------------------------------------------===// +// Pretty-printing regions. +//===----------------------------------------------------------------------===// + +namespace llvm { +static inline raw_ostream& operator<<(raw_ostream& os, + const clang::MemRegion* R) { + R->dumpToStream(os); + return os; +} +} // end llvm namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SVals.h new file mode 100644 index 0000000..040db83 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SVals.h @@ -0,0 +1,502 @@ +//== SVals.h - Abstract Values for Static Analysis ---------*- 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 SVal, Loc, and NonLoc, classes that represent +// abstract r-values for use with path-sensitive value tracking. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H +#define LLVM_CLANG_ANALYSIS_RVALUE_H + +#include "clang/Checker/PathSensitive/SymbolManager.h" +#include "llvm/Support/Casting.h" +#include "llvm/ADT/ImmutableList.h" + +namespace llvm { + class raw_ostream; +} + +//==------------------------------------------------------------------------==// +// Base SVal types. +//==------------------------------------------------------------------------==// + +namespace clang { + +class CompoundValData; +class LazyCompoundValData; +class GRState; +class BasicValueFactory; +class MemRegion; +class TypedRegion; +class MemRegionManager; +class GRStateManager; +class ValueManager; + +class SVal { +public: + enum BaseKind { UndefinedKind, UnknownKind, LocKind, NonLocKind }; + enum { BaseBits = 2, BaseMask = 0x3 }; + +protected: + void* Data; + unsigned Kind; + +protected: + SVal(const void* d, bool isLoc, unsigned ValKind) + : Data(const_cast<void*>(d)), + Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} + + explicit SVal(BaseKind k, void* D = NULL) + : Data(D), Kind(k) {} + +public: + SVal() : Data(0), Kind(0) {} + ~SVal() {} + + /// BufferTy - A temporary buffer to hold a set of SVals. + typedef llvm::SmallVector<SVal,5> BufferTy; + + inline unsigned getRawKind() const { return Kind; } + inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } + inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } + + inline void Profile(llvm::FoldingSetNodeID& ID) const { + ID.AddInteger((unsigned) getRawKind()); + ID.AddPointer(reinterpret_cast<void*>(Data)); + } + + inline bool operator==(const SVal& R) const { + return getRawKind() == R.getRawKind() && Data == R.Data; + } + + inline bool operator!=(const SVal& R) const { + return !(*this == R); + } + + inline bool isUnknown() const { + return getRawKind() == UnknownKind; + } + + inline bool isUndef() const { + return getRawKind() == UndefinedKind; + } + + inline bool isUnknownOrUndef() const { + return getRawKind() <= UnknownKind; + } + + inline bool isValid() const { + return getRawKind() > UnknownKind; + } + + bool isConstant() const; + + bool isZeroConstant() const; + + /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true; + bool hasConjuredSymbol() const; + + /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a + /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl. + /// 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 a SymbolData* + 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. + SymbolRef getAsSymbol() const; + + /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then + /// return that expression. Otherwise return NULL. + const SymExpr *getAsSymbolicExpression() const; + + const MemRegion *getAsRegion() const; + + void dumpToStream(llvm::raw_ostream& OS) const; + void dump() const; + + // Iterators. + class symbol_iterator { + llvm::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 { + const SymExpr *SE = getAsSymbolicExpression(); + if (SE) + return symbol_iterator(SE); + else + return symbol_iterator(); + } + + symbol_iterator symbol_end() const { return symbol_iterator(); } + + // Implement isa<T> support. + static inline bool classof(const SVal*) { return true; } +}; + + +class UndefinedVal : public SVal { +public: + UndefinedVal() : SVal(UndefinedKind) {} + UndefinedVal(void* D) : SVal(UndefinedKind, D) {} + + static inline bool classof(const SVal* V) { + return V->getBaseKind() == UndefinedKind; + } + + void* getData() const { return Data; } +}; + +class DefinedOrUnknownSVal : public SVal { +private: + // Do not implement. We want calling these methods to be a compiler + // error since they are tautologically false. + bool isUndef() const; + bool isValid() const; + +protected: + explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind) + : SVal(d, isLoc, ValKind) {} + + explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) + : SVal(k, D) {} + +public: + // Implement isa<T> support. + static inline bool classof(const SVal *V) { + return !V->isUndef(); + } +}; + +class UnknownVal : public DefinedOrUnknownSVal { +public: + UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} + + static inline bool classof(const SVal *V) { + return V->getBaseKind() == UnknownKind; + } +}; + +class DefinedSVal : public DefinedOrUnknownSVal { +private: + // Do not implement. We want calling these methods to be a compiler + // error since they are tautologically true/false. + bool isUnknown() const; + bool isUnknownOrUndef() const; + bool isValid() const; +protected: + DefinedSVal(const void* d, bool isLoc, unsigned ValKind) + : DefinedOrUnknownSVal(d, isLoc, ValKind) {} +public: + // Implement isa<T> support. + static inline bool classof(const SVal *V) { + return !V->isUnknownOrUndef(); + } +}; + +class NonLoc : public DefinedSVal { +protected: + NonLoc(unsigned SubKind, const void* d) : DefinedSVal(d, false, SubKind) {} + +public: + void dumpToStream(llvm::raw_ostream& Out) const; + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == NonLocKind; + } +}; + +class Loc : public DefinedSVal { +protected: + Loc(unsigned SubKind, const void* D) + : DefinedSVal(const_cast<void*>(D), true, SubKind) {} + +public: + void dumpToStream(llvm::raw_ostream& Out) const; + + Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {} + Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; } + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == LocKind; + } + + static inline bool IsLocType(QualType T) { + return T->isAnyPointerType() || T->isBlockPointerType() || + T->isReferenceType(); + } +}; + +//==------------------------------------------------------------------------==// +// Subclasses of NonLoc. +//==------------------------------------------------------------------------==// + +namespace nonloc { + +enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind, + LocAsIntegerKind, CompoundValKind, LazyCompoundValKind }; + +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; + } +}; + +class SymExprVal : public NonLoc { +public: + SymExprVal(const SymExpr *SE) + : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {} + + const SymExpr *getSymbolicExpression() const { + return reinterpret_cast<SymExpr*>(Data); + } + + static inline bool classof(const SVal* V) { + return V->getBaseKind() == NonLocKind && + V->getSubKind() == SymExprValKind; + } + + static inline bool classof(const NonLoc* V) { + return V->getSubKind() == SymExprValKind; + } +}; + +class ConcreteInt : public NonLoc { +public: + ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} + + const llvm::APSInt& getValue() const { + return *static_cast<llvm::APSInt*>(Data); + } + + // Transfer functions for binary/unary operations on ConcreteInts. + SVal evalBinOp(ValueManager &ValMgr, BinaryOperator::Opcode Op, + const ConcreteInt& R) const; + + ConcreteInt evalComplement(ValueManager &ValMgr) const; + + ConcreteInt evalMinus(ValueManager &ValMgr) const; + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == NonLocKind && + V->getSubKind() == ConcreteIntKind; + } + + static inline bool classof(const NonLoc* V) { + return V->getSubKind() == ConcreteIntKind; + } +}; + +class LocAsInteger : public NonLoc { + friend class clang::ValueManager; + + LocAsInteger(const std::pair<SVal, uintptr_t>& data) : + NonLoc(LocAsIntegerKind, &data) { + assert (isa<Loc>(data.first)); + } + +public: + + Loc getLoc() const { + return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first); + } + + const Loc& getPersistentLoc() const { + const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first; + return cast<Loc>(V); + } + + unsigned getNumBits() const { + return ((std::pair<SVal, unsigned>*) Data)->second; + } + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == NonLocKind && + V->getSubKind() == LocAsIntegerKind; + } + + static inline bool classof(const NonLoc* V) { + return V->getSubKind() == LocAsIntegerKind; + } +}; + +class CompoundVal : public NonLoc { + friend class clang::ValueManager; + + CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {} + +public: + const CompoundValData* getValue() const { + return static_cast<CompoundValData*>(Data); + } + + typedef llvm::ImmutableList<SVal>::iterator iterator; + iterator begin() const; + iterator end() const; + + static bool classof(const SVal* V) { + return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind; + } + + static bool classof(const NonLoc* V) { + return V->getSubKind() == CompoundValKind; + } +}; + +class LazyCompoundVal : public NonLoc { + friend class clang::ValueManager; + + LazyCompoundVal(const LazyCompoundValData *D) + : NonLoc(LazyCompoundValKind, D) {} +public: + const LazyCompoundValData *getCVData() const { + return static_cast<const LazyCompoundValData*>(Data); + } + const void *getStore() const; + const TypedRegion *getRegion() const; + + static bool classof(const SVal *V) { + return V->getBaseKind() == NonLocKind && + V->getSubKind() == LazyCompoundValKind; + } + static bool classof(const NonLoc *V) { + return V->getSubKind() == LazyCompoundValKind; + } +}; + +} // end namespace clang::nonloc + +//==------------------------------------------------------------------------==// +// Subclasses of Loc. +//==------------------------------------------------------------------------==// + +namespace loc { + +enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind }; + +class GotoLabel : public Loc { +public: + GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {} + + LabelStmt* getLabel() const { + return static_cast<LabelStmt*>(Data); + } + + static inline bool classof(const SVal* V) { + return V->getBaseKind() == LocKind && + V->getSubKind() == GotoLabelKind; + } + + static inline bool classof(const Loc* V) { + return V->getSubKind() == GotoLabelKind; + } +}; + + +class MemRegionVal : public Loc { +public: + MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} + + const MemRegion* getRegion() const { + return static_cast<MemRegion*>(Data); + } + + const MemRegion* StripCasts() const; + + template <typename REGION> + const REGION* getRegionAs() const { + return llvm::dyn_cast<REGION>(getRegion()); + } + + inline bool operator==(const MemRegionVal& R) const { + return getRegion() == R.getRegion(); + } + + inline bool operator!=(const MemRegionVal& R) const { + return getRegion() != R.getRegion(); + } + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == LocKind && + V->getSubKind() == MemRegionKind; + } + + static inline bool classof(const Loc* V) { + return V->getSubKind() == MemRegionKind; + } +}; + +class ConcreteInt : public Loc { +public: + ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} + + const llvm::APSInt& getValue() const { + return *static_cast<llvm::APSInt*>(Data); + } + + // Transfer functions for binary/unary operations on ConcreteInts. + SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, + const ConcreteInt& R) const; + + // Implement isa<T> support. + static inline bool classof(const SVal* V) { + return V->getBaseKind() == LocKind && + V->getSubKind() == ConcreteIntKind; + } + + static inline bool classof(const Loc* V) { + return V->getSubKind() == ConcreteIntKind; + } +}; + +} // end clang::loc namespace +} // end clang namespace + +namespace llvm { +static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os, + clang::SVal V) { + V.dumpToStream(os); + return os; +} +} // end llvm namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SValuator.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SValuator.h new file mode 100644 index 0000000..9beb8cb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SValuator.h @@ -0,0 +1,66 @@ +// SValuator.h - Construction of SVals from evaluating expressions -*- 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 SValuator, a class that defines the interface for +// "symbolical evaluators" which construct an SVal from an expression. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_SVALUATOR +#define LLVM_CLANG_ANALYSIS_SVALUATOR + +#include "clang/AST/Expr.h" +#include "clang/Checker/PathSensitive/SVals.h" + +namespace clang { + +class GRState; +class ValueManager; + +class SValuator { + friend class ValueManager; +protected: + ValueManager &ValMgr; + +public: + // FIXME: Make these protected again one RegionStoreManager correctly + // handles loads from differening bound value types. + virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0; + virtual SVal EvalCastL(Loc val, QualType castTy) = 0; + +public: + SValuator(ValueManager &valMgr) : ValMgr(valMgr) {} + virtual ~SValuator() {} + + SVal EvalCast(SVal V, QualType castTy, QualType originalType); + + virtual SVal EvalMinus(NonLoc val) = 0; + + virtual SVal EvalComplement(NonLoc val) = 0; + + virtual SVal EvalBinOpNN(const GRState *state, BinaryOperator::Opcode Op, + NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; + + virtual SVal EvalBinOpLL(BinaryOperator::Opcode Op, Loc lhs, Loc rhs, + QualType resultTy) = 0; + + virtual SVal EvalBinOpLN(const GRState *state, BinaryOperator::Opcode Op, + Loc lhs, NonLoc rhs, QualType resultTy) = 0; + + SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, + SVal L, SVal R, QualType T); + + DefinedOrUnknownSVal EvalEQ(const GRState *ST, DefinedOrUnknownSVal L, + DefinedOrUnknownSVal R); +}; + +SValuator* CreateSimpleSValuator(ValueManager &valMgr); + +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Store.h new file mode 100644 index 0000000..f3155b9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/Store.h @@ -0,0 +1,237 @@ +//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the types Store and StoreManager. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_STORE_H +#define LLVM_CLANG_ANALYSIS_STORE_H + +#include "clang/Checker/PathSensitive/MemRegion.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/ValueManager.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" + +namespace clang { + +typedef const void* Store; + +class GRState; +class GRStateManager; +class Stmt; +class Expr; +class ObjCIvarDecl; +class SubRegionMap; +class StackFrameContext; + +class StoreManager { +protected: + ValueManager &ValMgr; + GRStateManager &StateMgr; + + /// MRMgr - Manages region objects associated with this StoreManager. + MemRegionManager &MRMgr; + ASTContext &Ctx; + + StoreManager(GRStateManager &stateMgr); + +public: + virtual ~StoreManager() {} + + /// Return the value bound to specified location in a given state. + /// \param[in] state The analysis state. + /// \param[in] loc The symbolic memory location. + /// \param[in] T An optional type that provides a hint indicating the + /// 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; + + /// Return a state with the specified value bound to the given location. + /// \param[in] state The analysis state. + /// \param[in] loc The symbolic memory location. + /// \param[in] val The value to bind to location \c loc. + /// \return A pointer to a GRState object that contains the same bindings as + /// \c state with the addition of having the value specified by \c val bound + /// to the location given for \c loc. + virtual Store Bind(Store store, Loc loc, SVal val) = 0; + + virtual Store Remove(Store St, Loc L) = 0; + + /// BindCompoundLiteral - Return the store that has the bindings currently + /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region + /// for the compound literal and 'BegInit' and 'EndInit' represent an + /// array of initializer values. + virtual Store BindCompoundLiteral(Store store, + const CompoundLiteralExpr* cl, + const LocationContext *LC, SVal v) = 0; + + /// getInitialStore - Returns the initial "empty" store representing the + /// value bindings upon entry to an analyzed function. + virtual Store getInitialStore(const LocationContext *InitLoc) = 0; + + /// getRegionManager - Returns the internal RegionManager object that is + /// used to query and manipulate MemRegion objects. + MemRegionManager& getRegionManager() { return MRMgr; } + + /// getSubRegionMap - Returns an opaque map object that clients can query + /// to get the subregions of a given MemRegion object. It is the + // caller's responsibility to 'delete' the returned map. + virtual SubRegionMap *getSubRegionMap(Store store) = 0; + + virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) { + return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC)); + } + + virtual SVal getLValueString(const StringLiteral* S) { + return ValMgr.makeLoc(MRMgr.getStringRegion(S)); + } + + SVal 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 getLValueField(const FieldDecl* D, SVal Base) { + return getLValueFieldOrIvar(D, Base); + } + + virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base); + + // FIXME: Make out-of-line. + virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, + const MemRegion *region, + QualType EleTy) { + return UnknownVal(); + } + + /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit + /// conversions between arrays and pointers. + virtual SVal ArrayToPointer(Loc Array) = 0; + + class CastResult { + const GRState *state; + const MemRegion *region; + public: + const GRState *getState() const { return state; } + const MemRegion* getRegion() const { return region; } + CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){} + }; + + const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); + + /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from + /// a MemRegion* to a specific location type. 'R' is the region being + /// casted and 'CastToTy' the result type of the cast. + const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy); + + + /// EvalBinOp - Perform pointer arithmetic. + virtual SVal EvalBinOp(BinaryOperator::Opcode Op, + Loc lhs, NonLoc rhs, QualType resultTy) { + return UnknownVal(); + } + + virtual const GRState *RemoveDeadBindings(GRState &state, Stmt* Loc, + const StackFrameContext *LCtx, + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; + + virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; + + virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0; + + typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; + + virtual Store InvalidateRegion(Store store, + const MemRegion *R, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS) = 0; + + virtual Store InvalidateRegions(Store store, + const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS); + + // FIXME: Make out-of-line. + virtual const GRState *setExtent(const GRState *state, + const MemRegion *region, SVal extent) { + return state; + } + + virtual llvm::Optional<SVal> getExtent(const GRState *state, + const MemRegion *R) { + return llvm::Optional<SVal>(); + } + + /// EnterStackFrame - Let the StoreManager to do something when execution + /// engine is about to execute into a callee. + virtual const GRState *EnterStackFrame(const GRState *state, + const StackFrameContext *frame) { + return state; + } + + virtual void print(Store store, llvm::raw_ostream& Out, + const char* nl, const char *sep) = 0; + + class BindingsHandler { + public: + virtual ~BindingsHandler(); + virtual bool HandleBinding(StoreManager& SMgr, Store store, + const MemRegion *region, SVal val) = 0; + }; + + /// iterBindings - Iterate over the bindings in the Store. + virtual void iterBindings(Store store, BindingsHandler& f) = 0; + +protected: + const MemRegion *MakeElementRegion(const MemRegion *Base, + QualType pointeeTy, uint64_t index = 0); + + /// CastRetrievedVal - Used by subclasses of StoreManager to implement + /// implicit casts that arise from loads from regions that are reinterpreted + /// as another region. + SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy, + bool performTestOnly = true); + +private: + SVal getLValueFieldOrIvar(const Decl* D, SVal Base); +}; + +// FIXME: Do we still need this? +/// SubRegionMap - An abstract interface that represents a queryable map +/// between MemRegion objects and their subregions. +class SubRegionMap { +public: + virtual ~SubRegionMap() {} + + class Visitor { + public: + virtual ~Visitor() {} + virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; + }; + + virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0; +}; + +// FIXME: Do we need to pass GRStateManager anymore? +StoreManager *CreateBasicStoreManager(GRStateManager& StMgr); +StoreManager *CreateRegionStoreManager(GRStateManager& StMgr); +StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr); +StoreManager *CreateFlatStoreManager(GRStateManager &StMgr); +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SummaryManager.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SummaryManager.h new file mode 100644 index 0000000..fd23189 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SummaryManager.h @@ -0,0 +1,57 @@ +//== SummaryManager.h - Generic handling of function summaries --*- 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 SummaryManager and related classes, which provides +// a generic mechanism for managing function summaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_SUMMARY +#define LLVM_CLANG_CHECKER_SUMMARY + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" + +namespace clang { + +namespace summMgr { + + +/* Key kinds: + + - C functions + - C++ functions (name + parameter types) + - ObjC methods: + - Class, selector (class method) + - Class, selector (instance method) + - Category, selector (instance method) + - Protocol, selector (instance method) + - C++ methods + - Class, function name + parameter types + const + */ + +class SummaryKey { + +}; + +} // end namespace clang::summMgr + +class SummaryManagerImpl { + +}; + + +template <typename T> +class SummaryManager : SummaryManagerImpl { + +}; + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SymbolManager.h new file mode 100644 index 0000000..dea877c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/SymbolManager.h @@ -0,0 +1,379 @@ +//== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values +// created for use by GRExprEngine and related classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H +#define LLVM_CLANG_ANALYSIS_SYMMGR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/Analysis/AnalysisContext.h" +#include "llvm/System/DataTypes.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseSet.h" + +namespace llvm { +class BumpPtrAllocator; +class raw_ostream; +} + +namespace clang { + class ASTContext; + class BasicValueFactory; + class MemRegion; + class TypedRegion; + class VarRegion; + class StackFrameContext; + +class SymExpr : public llvm::FoldingSetNode { +public: + enum Kind { BEGIN_SYMBOLS, + RegionValueKind, ConjuredKind, DerivedKind, + END_SYMBOLS, + SymIntKind, SymSymKind }; +private: + Kind K; + +protected: + SymExpr(Kind k) : K(k) {} + +public: + virtual ~SymExpr() {} + + Kind getKind() const { return K; } + + void dump() const; + + virtual void dumpToStream(llvm::raw_ostream &os) const = 0; + + 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; } +}; + +typedef unsigned SymbolID; + +class SymbolData : public SymExpr { +private: + const SymbolID Sym; + +protected: + SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} + +public: + virtual ~SymbolData() {} + + SymbolID getSymbolID() const { return Sym; } + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + Kind k = SE->getKind(); + return k > BEGIN_SYMBOLS && k < END_SYMBOLS; + } +}; + +typedef const SymbolData* SymbolRef; + +// A symbol representing the value of a MemRegion. +class SymbolRegionValue : public SymbolData { + const TypedRegion *R; + +public: + SymbolRegionValue(SymbolID sym, const TypedRegion *r) + : SymbolData(RegionValueKind, sym), R(r) {} + + const TypedRegion* getRegion() const { return R; } + + static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) { + profile.AddInteger((unsigned) RegionValueKind); + profile.AddPointer(R); + } + + virtual void Profile(llvm::FoldingSetNodeID& profile) { + Profile(profile, R); + } + + void dumpToStream(llvm::raw_ostream &os) const; + + QualType getType(ASTContext&) const; + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == RegionValueKind; + } +}; + +// A symbol representing the result of an expression. +class SymbolConjured : public SymbolData { + const Stmt* S; + QualType T; + unsigned Count; + const void* SymbolTag; + +public: + SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count, + const void* symbolTag) + : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), + SymbolTag(symbolTag) {} + + const Stmt* getStmt() const { return S; } + unsigned getCount() const { return Count; } + const void* getTag() const { return SymbolTag; } + + QualType getType(ASTContext&) const; + + void dumpToStream(llvm::raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& profile, const Stmt* S, + QualType T, unsigned Count, const void* SymbolTag) { + profile.AddInteger((unsigned) ConjuredKind); + profile.AddPointer(S); + profile.Add(T); + profile.AddInteger(Count); + profile.AddPointer(SymbolTag); + } + + virtual void Profile(llvm::FoldingSetNodeID& profile) { + Profile(profile, S, T, Count, SymbolTag); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == ConjuredKind; + } +}; + +// A symbol representing the value of a MemRegion whose parent region has +// symbolic value. +class SymbolDerived : public SymbolData { + SymbolRef parentSymbol; + const TypedRegion *R; + +public: + SymbolDerived(SymbolID sym, SymbolRef parent, const TypedRegion *r) + : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {} + + SymbolRef getParentSymbol() const { return parentSymbol; } + const TypedRegion *getRegion() const { return R; } + + QualType getType(ASTContext&) const; + + void dumpToStream(llvm::raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, + const TypedRegion *r) { + profile.AddInteger((unsigned) DerivedKind); + profile.AddPointer(r); + profile.AddPointer(parent); + } + + virtual void Profile(llvm::FoldingSetNodeID& profile) { + Profile(profile, parentSymbol, R); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == DerivedKind; + } +}; + +// SymIntExpr - Represents symbolic expression like 'x' + 3. +class SymIntExpr : public SymExpr { + const SymExpr *LHS; + BinaryOperator::Opcode Op; + const llvm::APSInt& RHS; + QualType T; + +public: + SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t) + : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} + + // FIXME: We probably need to make this out-of-line to avoid redundant + // generation of virtual functions. + QualType getType(ASTContext& C) const { return T; } + + BinaryOperator::Opcode getOpcode() const { return Op; } + + void dumpToStream(llvm::raw_ostream &os) const; + + const SymExpr *getLHS() const { return LHS; } + const llvm::APSInt &getRHS() const { return RHS; } + + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, + BinaryOperator::Opcode op, const llvm::APSInt& rhs, + QualType t) { + ID.AddInteger((unsigned) SymIntKind); + 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() == SymIntKind; + } +}; + +// SymSymExpr - Represents symbolic expression like 'x' + 'y'. +class SymSymExpr : public SymExpr { + const SymExpr *LHS; + BinaryOperator::Opcode Op; + const SymExpr *RHS; + QualType T; + +public: + SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, + QualType t) + : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} + + BinaryOperator::Opcode getOpcode() const { return Op; } + const SymExpr *getLHS() const { return LHS; } + const SymExpr *getRHS() const { return RHS; } + + // FIXME: We probably need to make this out-of-line to avoid redundant + // generation of virtual functions. + QualType getType(ASTContext& C) const { return T; } + + void dumpToStream(llvm::raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { + ID.AddInteger((unsigned) SymSymKind); + 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() == SymSymKind; + } +}; + +class SymbolManager { + typedef llvm::FoldingSet<SymExpr> DataSetTy; + DataSetTy DataSet; + unsigned SymbolCounter; + llvm::BumpPtrAllocator& BPAlloc; + BasicValueFactory &BV; + ASTContext& Ctx; + +public: + SymbolManager(ASTContext& ctx, BasicValueFactory &bv, + llvm::BumpPtrAllocator& bpalloc) + : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} + + ~SymbolManager(); + + static bool canSymbolicate(QualType T); + + /// Make a unique symbol for MemRegion R according to its kind. + const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R); + + const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, + unsigned VisitCount, + const void* SymbolTag = 0); + + const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount, + const void* SymbolTag = 0) { + return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag); + } + + const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, + const TypedRegion *R); + + const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t); + + const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t) { + return getSymIntExpr(&lhs, op, rhs, t); + } + + const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const SymExpr *rhs, QualType t); + + QualType getType(const SymExpr *SE) const { + return SE->getType(Ctx); + } + + ASTContext &getContext() { return Ctx; } + BasicValueFactory &getBasicVals() { return BV; } +}; + +class SymbolReaper { + typedef llvm::DenseSet<SymbolRef> SetTy; + + SetTy TheLiving; + SetTy TheDead; + const LocationContext *LCtx; + SymbolManager& SymMgr; + +public: + SymbolReaper(const LocationContext *ctx, SymbolManager& symmgr) + : LCtx(ctx), SymMgr(symmgr) {} + + ~SymbolReaper() {} + + const LocationContext *getLocationContext() const { return LCtx; } + + bool isLive(SymbolRef sym); + + bool isLive(const Stmt* Loc, const Stmt* ExprVal) const; + + bool isLive(const Stmt* Loc, const VarRegion *VR) const; + + void markLive(SymbolRef sym); + bool maybeDead(SymbolRef sym); + + typedef SetTy::const_iterator dead_iterator; + dead_iterator dead_begin() const { return TheDead.begin(); } + dead_iterator dead_end() const { return TheDead.end(); } + + bool hasDeadSymbols() const { + return !TheDead.empty(); + } +}; + +class SymbolVisitor { +public: + // VisitSymbol - A visitor method invoked by + // GRStateManager::scanReachableSymbols. The method returns \c true if + // symbols should continue be scanned and \c false otherwise. + virtual bool VisitSymbol(SymbolRef sym) = 0; + virtual ~SymbolVisitor(); +}; + +} // end clang namespace + +namespace llvm { +static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os, + const clang::SymExpr *SE) { + SE->dumpToStream(os); + return os; +} +} // end llvm namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ValueManager.h b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ValueManager.h new file mode 100644 index 0000000..5a9d54d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Checker/PathSensitive/ValueManager.h @@ -0,0 +1,213 @@ +//== ValueManager.h - Aggregate manager of symbols and SVals ----*- 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 ValueManager, a class that manages symbolic values +// and SVals created for use by GRExprEngine and related classes. It +// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H +#define LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H + +#include "llvm/ADT/OwningPtr.h" +#include "clang/Checker/PathSensitive/MemRegion.h" +#include "clang/Checker/PathSensitive/SVals.h" +#include "clang/Checker/PathSensitive/BasicValueFactory.h" +#include "clang/Checker/PathSensitive/SymbolManager.h" +#include "clang/Checker/PathSensitive/SValuator.h" +#include "clang/AST/ExprCXX.h" + +namespace llvm { class BumpPtrAllocator; } + +namespace clang { + +class GRStateManager; + +class ValueManager { + + ASTContext &Context; + BasicValueFactory BasicVals; + + /// SymMgr - Object that manages the symbol information. + SymbolManager SymMgr; + + /// SVator - SValuator object that creates SVals from expressions. + llvm::OwningPtr<SValuator> SVator; + + MemRegionManager MemMgr; + + GRStateManager &StateMgr; + + const QualType ArrayIndexTy; + const unsigned ArrayIndexWidth; + +public: + ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context, + GRStateManager &stateMgr) + : Context(context), BasicVals(context, alloc), + SymMgr(context, BasicVals, alloc), + MemMgr(context, alloc), StateMgr(stateMgr), + ArrayIndexTy(context.IntTy), + ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) { + // FIXME: Generalize later. + SVator.reset(clang::CreateSimpleSValuator(*this)); + } + + // Accessors to submanagers. + + ASTContext &getContext() { return Context; } + const ASTContext &getContext() const { return Context; } + + GRStateManager &getStateManager() { return StateMgr; } + + BasicValueFactory &getBasicValueFactory() { return BasicVals; } + const BasicValueFactory &getBasicValueFactory() const { return BasicVals; } + + SymbolManager &getSymbolManager() { return SymMgr; } + const SymbolManager &getSymbolManager() const { return SymMgr; } + + SValuator &getSValuator() { return *SVator.get(); } + + MemRegionManager &getRegionManager() { return MemMgr; } + const MemRegionManager &getRegionManager() const { return MemMgr; } + + // Forwarding methods to SymbolManager. + + const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, + unsigned VisitCount, + const void* SymbolTag = 0) { + return SymMgr.getConjuredSymbol(E, T, VisitCount, SymbolTag); + } + + const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount, + const void* SymbolTag = 0) { + return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag); + } + + /// makeZeroVal - Construct an SVal representing '0' for the specified type. + DefinedOrUnknownSVal makeZeroVal(QualType T); + + /// getRegionValueSymbolVal - make a unique symbol for value of R. + DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R); + + DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, + const Expr *E, QualType T, + unsigned Count); + + DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, + const TypedRegion *R); + + DefinedSVal getFunctionPointer(const FunctionDecl *FD); + + DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy, + const LocationContext *LC); + + NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) { + return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); + } + + NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) { + return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R)); + } + + NonLoc makeZeroArrayIndex() { + return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy)); + } + + NonLoc makeArrayIndex(uint64_t idx) { + return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy)); + } + + SVal convertToArrayIndex(SVal V); + + nonloc::ConcreteInt makeIntVal(const IntegerLiteral* I) { + return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(), + I->getType()->isUnsignedIntegerType())); + } + + nonloc::ConcreteInt makeIntVal(const CXXBoolLiteralExpr *E) { + return E->getValue() ? nonloc::ConcreteInt(BasicVals.getValue(1, 1, true)) + : nonloc::ConcreteInt(BasicVals.getValue(0, 1, true)); + } + + nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) { + return nonloc::ConcreteInt(BasicVals.getValue(V)); + } + + loc::ConcreteInt makeIntLocVal(const llvm::APSInt &v) { + return loc::ConcreteInt(BasicVals.getValue(v)); + } + + NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned)); + } + + DefinedSVal makeIntVal(uint64_t X, QualType T) { + if (Loc::IsLocType(T)) + return loc::ConcreteInt(BasicVals.getValue(X, T)); + + return nonloc::ConcreteInt(BasicVals.getValue(X, T)); + } + + NonLoc makeIntVal(uint64_t X, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned)); + } + + NonLoc makeIntValWithPtrWidth(uint64_t X, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getIntWithPtrWidth(X, isUnsigned)); + } + + NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned)); + } + + NonLoc makeLocAsInteger(Loc V, unsigned Bits) { + return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits)); + } + + NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType T); + + NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, + const SymExpr *rhs, QualType T); + + NonLoc makeTruthVal(bool b, QualType T) { + return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T)); + } + + NonLoc makeTruthVal(bool b) { + return nonloc::ConcreteInt(BasicVals.getTruthValue(b)); + } + + Loc makeNull() { + return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth()); + } + + Loc makeLoc(SymbolRef Sym) { + return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym)); + } + + Loc makeLoc(const MemRegion* R) { + return loc::MemRegionVal(R); + } + + Loc makeLoc(const AddrLabelExpr* E) { + return loc::GotoLabel(E->getLabel()); + } + + Loc makeLoc(const llvm::APSInt& V) { + return loc::ConcreteInt(BasicVals.getValue(V)); + } +}; +} // end clang namespace +#endif + diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenOptions.h new file mode 100644 index 0000000..6241230 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenOptions.h @@ -0,0 +1,131 @@ +//===--- CodeGenOptions.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 defines the CodeGenOptions interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H +#define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H + +#include <string> + +namespace clang { + +/// CodeGenOptions - Track various options which control how the code +/// is optimized and passed to the backend. +class CodeGenOptions { +public: + enum InliningMethod { + NoInlining, // Perform no inlining whatsoever. + NormalInlining, // Use the standard function inlining pass. + OnlyAlwaysInlining // Only run the always inlining pass. + }; + + enum ObjCDispatchMethodKind { + Legacy = 0, + NonLegacy = 1, + Mixed = 2 + }; + + unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. + unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. + unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker + /// aliases to base ctors when possible. + unsigned DataSections : 1; /// Set when -fdata-sections is enabled + unsigned DebugInfo : 1; /// Should generate deubg info (-g). + unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled. + unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in + /// getting .bc files that correspond to the + /// internal state before optimizations are + /// done. + unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. + unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled + unsigned MergeAllConstants : 1; /// Merge identical constants. + unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. + unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. + unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss + unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. + unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. + unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned RelaxAll : 1; /// Relax all machine code instructions. + unsigned SoftFloat : 1; /// -soft-float. + unsigned TimePasses : 1; /// Set when -ftime-report is enabled. + unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization + /// selection. + unsigned UnrollLoops : 1; /// Control whether loops are unrolled. + unsigned UnwindTables : 1; /// Emit unwind tables. + unsigned VerifyModule : 1; /// Control whether the module should be run + /// through the LLVM Verifier. + + /// The code model to use (-mcmodel). + std::string CodeModel; + + /// Enable additional debugging information. + std::string DebugPass; + + /// The string to embed in the debug information for the compile unit, if + /// non-empty. + std::string DwarfDebugFlags; + + /// The ABI to use for passing floating point arguments. + std::string FloatABI; + + /// The float precision limit to use, if non-empty. + std::string LimitFloatPrecision; + + /// The kind of inlining to perform. + InliningMethod Inlining; + + /// The user provided name for the "main file", if non-empty. This is useful + /// in situations where the input file name does not match the original input + /// file, for example with -save-temps. + std::string MainFileName; + + /// The name of the relocation model to use. + std::string RelocationModel; + +public: + CodeGenOptions() { + AsmVerbose = 0; + CXAAtExit = 1; + CXXCtorDtorAliases = 0; + DataSections = 0; + DebugInfo = 0; + DisableFPElim = 0; + DisableLLVMOpts = 0; + DisableRedZone = 0; + FunctionSections = 0; + MergeAllConstants = 1; + NoCommon = 0; + NoImplicitFloat = 0; + NoZeroInitializedInBSS = 0; + ObjCDispatchMethod = Legacy; + OptimizationLevel = 0; + OptimizeSize = 0; + RelaxAll = 0; + SoftFloat = 0; + TimePasses = 0; + UnitAtATime = 1; + UnrollLoops = 0; + UnwindTables = 0; + VerifyModule = 1; + + Inlining = NoInlining; + RelocationModel = "pic"; + } + + ObjCDispatchMethodKind getObjCDispatchMethod() const { + return ObjCDispatchMethodKind(ObjCDispatchMethod); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h new file mode 100644 index 0000000..2a3aa6a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h @@ -0,0 +1,42 @@ +//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- 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 ModuleBuilder interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H +#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H + +#include "clang/AST/ASTConsumer.h" +#include <string> + +namespace llvm { + class LLVMContext; + class Module; +} + +namespace clang { + class Diagnostic; + class LangOptions; + class CodeGenOptions; + + class CodeGenerator : public ASTConsumer { + public: + virtual llvm::Module* GetModule() = 0; + virtual llvm::Module* ReleaseModule() = 0; + }; + + CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags, + const std::string &ModuleName, + const CodeGenOptions &CGO, + llvm::LLVMContext& C); +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h new file mode 100644 index 0000000..ab3162a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h @@ -0,0 +1,217 @@ +//===--- Action.h - Abstract compilation steps ------------------*- 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_ACTION_H_ +#define CLANG_DRIVER_ACTION_H_ + +#include "llvm/ADT/SmallVector.h" + +#include "clang/Driver/Types.h" +#include "clang/Driver/Util.h" + +#include "llvm/Support/Casting.h" +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; + +namespace clang { +namespace driver { + class Arg; + +/// Action - Represent an abstract compilation step to perform. +/// +/// An action represents an edge in the compilation graph; typically +/// it is a job to transform an input using some tool. +/// +/// The current driver is hard wired to expect actions which produce a +/// single primary output, at least in terms of controlling the +/// compilation. Actions can produce auxiliary files, but can only +/// produce a single output to feed into subsequent actions. +class Action { +public: + typedef ActionList::size_type size_type; + typedef ActionList::iterator iterator; + typedef ActionList::const_iterator const_iterator; + + enum ActionClass { + InputClass = 0, + BindArchClass, + PreprocessJobClass, + PrecompileJobClass, + AnalyzeJobClass, + CompileJobClass, + AssembleJobClass, + LinkJobClass, + LipoJobClass, + + JobClassFirst=PreprocessJobClass, + JobClassLast=LipoJobClass + }; + + static const char *getClassName(ActionClass AC); + +private: + ActionClass Kind; + + /// The output type of this action. + types::ID Type; + + ActionList Inputs; + + unsigned OwnsInputs : 1; + +protected: + Action(ActionClass _Kind, types::ID _Type) + : Kind(_Kind), Type(_Type), OwnsInputs(true) {} + Action(ActionClass _Kind, Action *Input, types::ID _Type) + : Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1), OwnsInputs(true) {} + Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type) + : Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {} +public: + virtual ~Action(); + + const char *getClassName() const { return Action::getClassName(getKind()); } + + bool getOwnsInputs() { return OwnsInputs; } + void setOwnsInputs(bool Value) { OwnsInputs = Value; } + + ActionClass getKind() const { return Kind; } + types::ID getType() const { return Type; } + + ActionList &getInputs() { return Inputs; } + const ActionList &getInputs() const { return Inputs; } + + size_type size() const { return Inputs.size(); } + + iterator begin() { return Inputs.begin(); } + iterator end() { return Inputs.end(); } + const_iterator begin() const { return Inputs.begin(); } + const_iterator end() const { return Inputs.end(); } + + static bool classof(const Action *) { return true; } +}; + +class InputAction : public Action { + const Arg &Input; +public: + InputAction(const Arg &_Input, types::ID _Type); + + const Arg &getInputArg() const { return Input; } + + static bool classof(const Action *A) { + return A->getKind() == InputClass; + } + static bool classof(const InputAction *) { return true; } +}; + +class BindArchAction : public Action { + /// The architecture to bind, or 0 if the default architecture + /// should be bound. + const char *ArchName; + +public: + BindArchAction(Action *Input, const char *_ArchName); + + const char *getArchName() const { return ArchName; } + + static bool classof(const Action *A) { + return A->getKind() == BindArchClass; + } + static bool classof(const BindArchAction *) { return true; } +}; + +class JobAction : public Action { +protected: + JobAction(ActionClass Kind, Action *Input, types::ID Type); + JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); + +public: + static bool classof(const Action *A) { + return (A->getKind() >= JobClassFirst && + A->getKind() <= JobClassLast); + } + static bool classof(const JobAction *) { return true; } +}; + +class PreprocessJobAction : public JobAction { +public: + PreprocessJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == PreprocessJobClass; + } + static bool classof(const PreprocessJobAction *) { return true; } +}; + +class PrecompileJobAction : public JobAction { +public: + PrecompileJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == PrecompileJobClass; + } + static bool classof(const PrecompileJobAction *) { return true; } +}; + +class AnalyzeJobAction : public JobAction { +public: + AnalyzeJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == AnalyzeJobClass; + } + static bool classof(const AnalyzeJobAction *) { return true; } +}; + +class CompileJobAction : public JobAction { +public: + CompileJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == CompileJobClass; + } + static bool classof(const CompileJobAction *) { return true; } +}; + +class AssembleJobAction : public JobAction { +public: + AssembleJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == AssembleJobClass; + } + static bool classof(const AssembleJobAction *) { return true; } +}; + +class LinkJobAction : public JobAction { +public: + LinkJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == LinkJobClass; + } + static bool classof(const LinkJobAction *) { return true; } +}; + +class LipoJobAction : public JobAction { +public: + LipoJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == LipoJobClass; + } + static bool classof(const LipoJobAction *) { return true; } +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Arg.h b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h new file mode 100644 index 0000000..ebf40d4 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h @@ -0,0 +1,230 @@ +//===--- Arg.h - Parsed Argument Classes ------------------------*- 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_ARG_H_ +#define CLANG_DRIVER_ARG_H_ + +#include "llvm/Support/Casting.h" +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; + +#include "Util.h" +#include <vector> +#include <string> + +namespace clang { +namespace driver { + class ArgList; + class Option; + + /// Arg - A concrete instance of a particular driver option. + /// + /// The Arg class encodes just enough information to be able to + /// derive the argument values efficiently. In addition, Arg + /// instances have an intrusive double linked list which is used by + /// ArgList to provide efficient iteration over all instances of a + /// particular option. + class Arg { + public: + enum ArgClass { + FlagClass = 0, + PositionalClass, + JoinedClass, + SeparateClass, + CommaJoinedClass, + JoinedAndSeparateClass + }; + + private: + ArgClass Kind; + + /// The option this argument is an instance of. + const Option *Opt; + + /// The argument this argument was derived from (during tool chain + /// argument translation), if any. + const Arg *BaseArg; + + /// The index at which this argument appears in the containing + /// ArgList. + unsigned Index; + + /// Flag indicating whether this argument was used to effect + /// compilation; used for generating "argument unused" + /// diagnostics. + mutable bool Claimed; + + protected: + Arg(ArgClass Kind, const Option *Opt, unsigned Index, + const Arg *BaseArg = 0); + + public: + Arg(const Arg &); + virtual ~Arg(); + + ArgClass getKind() const { return Kind; } + const Option &getOption() const { return *Opt; } + unsigned getIndex() const { return Index; } + + /// getBaseArg - Return the base argument which generated this + /// arg; this is either the argument itself or the argument it was + /// derived from during tool chain specific argument translation. + const Arg &getBaseArg() const { + return BaseArg ? *BaseArg : *this; + } + void setBaseArg(const Arg *_BaseArg) { + BaseArg = _BaseArg; + } + + bool isClaimed() const { return getBaseArg().Claimed; } + + /// claim - Set the Arg claimed bit. + + // FIXME: We need to deal with derived arguments and set the bit + // in the original argument; not the derived one. + void claim() const { getBaseArg().Claimed = true; } + + virtual unsigned getNumValues() const = 0; + virtual const char *getValue(const ArgList &Args, unsigned N=0) const = 0; + + /// render - Append the argument onto the given array as strings. + virtual void render(const ArgList &Args, ArgStringList &Output) const = 0; + + /// renderAsInput - Append the argument, render as an input, onto + /// the given array as strings. The distinction is that some + /// options only render their values when rendered as a input + /// (e.g., Xlinker). + void renderAsInput(const ArgList &Args, ArgStringList &Output) const; + + static bool classof(const Arg *) { return true; } + + void dump() const; + + /// getAsString - Return a formatted version of the argument and + /// its values, for debugging and diagnostics. + std::string getAsString(const ArgList &Args) const; + }; + + /// FlagArg - An argument with no value. + class FlagArg : public Arg { + public: + FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return 0; } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::FlagClass; + } + static bool classof(const FlagArg *) { return true; } + }; + + /// PositionalArg - A simple positional argument. + class PositionalArg : public Arg { + public: + PositionalArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return 1; } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::PositionalClass; + } + static bool classof(const PositionalArg *) { return true; } + }; + + /// JoinedArg - A single value argument where the value is joined + /// (suffixed) to the option. + class JoinedArg : public Arg { + public: + JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return 1; } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::JoinedClass; + } + static bool classof(const JoinedArg *) { return true; } + }; + + /// SeparateArg - An argument where one or more values follow the + /// option specifier immediately in the argument vector. + class SeparateArg : public Arg { + unsigned NumValues; + + public: + SeparateArg(const Option *Opt, unsigned Index, unsigned NumValues, + const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return NumValues; } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::SeparateClass; + } + static bool classof(const SeparateArg *) { return true; } + }; + + /// CommaJoinedArg - An argument with multiple values joined by + /// commas and joined (suffixed) to the option specifier. + /// + /// The key point of this arg is that it renders its values into + /// separate arguments, which allows it to be used as a generic + /// mechanism for passing arguments through to tools. + class CommaJoinedArg : public Arg { + std::vector<std::string> Values; + + public: + CommaJoinedArg(const Option *Opt, unsigned Index, const char *Str, + const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return Values.size(); } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::CommaJoinedClass; + } + static bool classof(const CommaJoinedArg *) { return true; } + }; + + /// JoinedAndSeparateArg - An argument with both joined and separate + /// values. + class JoinedAndSeparateArg : public Arg { + public: + JoinedAndSeparateArg(const Option *Opt, unsigned Index, + const Arg *BaseArg = 0); + + virtual void render(const ArgList &Args, ArgStringList &Output) const; + + virtual unsigned getNumValues() const { return 2; } + virtual const char *getValue(const ArgList &Args, unsigned N=0) const; + + static bool classof(const Arg *A) { + return A->getKind() == Arg::JoinedAndSeparateClass; + } + static bool classof(const JoinedAndSeparateArg *) { return true; } + }; +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h new file mode 100644 index 0000000..7a14ae8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h @@ -0,0 +1,359 @@ +//===--- ArgList.h - Argument List Management ----------*- 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_ARGLIST_H_ +#define CLANG_DRIVER_ARGLIST_H_ + +#include "clang/Driver/OptSpecifier.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +#include <list> +#include <string> +#include <vector> + +namespace llvm { + class Twine; +} + +namespace clang { + class Diagnostic; + +namespace driver { + class Arg; + class ArgList; + class Option; + + /// arg_iterator - Iterates through arguments stored inside an ArgList. + class arg_iterator { + /// The current argument. + llvm::SmallVectorImpl<Arg*>::const_iterator Current; + + /// The argument list we are iterating over. + const ArgList &Args; + + /// Optional filters on the arguments which will be match. Most clients + /// should never want to iterate over arguments without filters, so we won't + /// bother to factor this into two separate iterator implementations. + // + // FIXME: Make efficient; the idea is to provide efficient iteration over + // all arguments which match a particular id and then just provide an + // iterator combinator which takes multiple iterators which can be + // efficiently compared and returns them in order. + OptSpecifier Id0, Id1, Id2; + + void SkipToNextArg(); + + public: + typedef const Arg* value_type; + typedef const Arg* reference; + typedef const Arg* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it, + const ArgList &_Args, OptSpecifier _Id0 = 0U, + OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U) + : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) { + SkipToNextArg(); + } + + operator const Arg*() { return *Current; } + reference operator*() const { return *Current; } + pointer operator->() const { return *Current; } + + arg_iterator &operator++() { + ++Current; + SkipToNextArg(); + return *this; + } + + arg_iterator operator++(int) { + arg_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(arg_iterator LHS, arg_iterator RHS) { + return LHS.Current == RHS.Current; + } + friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { + return !(LHS == RHS); + } + }; + + /// ArgList - Ordered collection of driver arguments. + /// + /// The ArgList class manages a list of Arg instances as well as + /// auxiliary data and convenience methods to allow Tools to quickly + /// check for the presence of Arg instances for a particular Option + /// and to iterate over groups of arguments. + class ArgList { + public: + typedef llvm::SmallVector<Arg*, 16> arglist_type; + typedef arglist_type::iterator iterator; + typedef arglist_type::const_iterator const_iterator; + typedef arglist_type::reverse_iterator reverse_iterator; + typedef arglist_type::const_reverse_iterator const_reverse_iterator; + + private: + /// The full list of arguments. + arglist_type &Args; + + protected: + ArgList(arglist_type &Args); + + public: + virtual ~ArgList(); + + /// @name Arg Access + /// @{ + + /// append - Append \arg A to the arg list. + void append(Arg *A); + + arglist_type &getArgs() { return Args; } + const arglist_type &getArgs() const { return Args; } + + unsigned size() const { return Args.size(); } + + /// @} + /// @name Arg Iteration + /// @{ + + iterator begin() { return Args.begin(); } + iterator end() { return Args.end(); } + + reverse_iterator rbegin() { return Args.rbegin(); } + reverse_iterator rend() { return Args.rend(); } + + const_iterator begin() const { return Args.begin(); } + const_iterator end() const { return Args.end(); } + + const_reverse_iterator rbegin() const { return Args.rbegin(); } + const_reverse_iterator rend() const { return Args.rend(); } + + arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); + } + arg_iterator filtered_end() const { + return arg_iterator(Args.end(), *this); + } + + /// @} + /// @name Arg Access + /// @{ + + /// hasArg - Does the arg list contain any option matching \arg Id. + /// + /// \arg Claim Whether the argument should be claimed, if it exists. + bool hasArgNoClaim(OptSpecifier Id) const { + return getLastArgNoClaim(Id) != 0; + } + bool hasArg(OptSpecifier Id) const { + return getLastArg(Id) != 0; + } + bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const { + return getLastArg(Id0, Id1) != 0; + } + bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { + return getLastArg(Id0, Id1, Id2) != 0; + } + + /// getLastArg - Return the last argument matching \arg Id, or null. + /// + /// \arg Claim Whether the argument should be claimed, if it exists. + Arg *getLastArgNoClaim(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; + + /// getArgString - Return the input argument string at \arg Index. + virtual const char *getArgString(unsigned Index) const = 0; + + /// @} + /// @name Argument Lookup Utilities + /// @{ + + /// getLastArgValue - Return the value of the last argument, or a default. + llvm::StringRef getLastArgValue(OptSpecifier Id, + llvm::StringRef Default = "") 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, + Diagnostic &Diags) const; + + /// getAllArgValues - Get the values of all instances of the given argument + /// as strings. + std::vector<std::string> getAllArgValues(OptSpecifier Id) const; + + /// @} + /// @name Translation Utilities + /// @{ + + /// hasFlag - Given an option \arg Pos and its negative form \arg + /// Neg, return true if the option is present, false if the + /// negation is present, and \arg Default if neither option is + /// given. If both the option and its negation are present, the + /// last one wins. + bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; + + /// AddLastArg - Render only the last argument match \arg Id0, if + /// present. + void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; + + /// AddAllArgs - Render all arguments matching the given ids. + void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; + + /// AddAllArgValues - Render the argument values of all arguments + /// matching the given ids. + void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; + + /// AddAllArgsTranslated - Render all the arguments matching the + /// given ids, but forced to separate args and using the provided + /// name instead of the first option value. + /// + /// \param Joined - If true, render the argument as joined with + /// the option specifier. + void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, + const char *Translation, + bool Joined = false) const; + + /// ClaimAllArgs - Claim all arguments which match the given + /// option id. + void ClaimAllArgs(OptSpecifier Id0) const; + + /// @} + /// @name Arg Synthesis + /// @{ + + /// MakeArgString - Construct a constant string pointer whose + /// lifetime will match that of the ArgList. + virtual const char *MakeArgString(llvm::StringRef Str) const = 0; + const char *MakeArgString(const char *Str) const { + return MakeArgString(llvm::StringRef(Str)); + } + const char *MakeArgString(std::string Str) const { + return MakeArgString(llvm::StringRef(Str)); + } + const char *MakeArgString(const llvm::Twine &Str) const; + + /// @} + }; + + class InputArgList : public ArgList { + private: + /// The internal list of arguments. + arglist_type ActualArgs; + + /// List of argument strings used by the contained Args. + /// + /// This is mutable since we treat the ArgList as being the list + /// of Args, and allow routines to add new strings (to have a + /// convenient place to store the memory) via MakeIndex. + mutable ArgStringList ArgStrings; + + /// Strings for synthesized arguments. + /// + /// This is mutable since we treat the ArgList as being the list + /// of Args, and allow routines to add new strings (to have a + /// convenient place to store the memory) via MakeIndex. + mutable std::list<std::string> SynthesizedStrings; + + /// The number of original input argument strings. + unsigned NumInputArgStrings; + + public: + InputArgList(const char **ArgBegin, const char **ArgEnd); + InputArgList(const ArgList &); + ~InputArgList(); + + virtual const char *getArgString(unsigned Index) const { + return ArgStrings[Index]; + } + + /// getNumInputArgStrings - Return the number of original input + /// argument strings. + unsigned getNumInputArgStrings() const { return NumInputArgStrings; } + + /// @name Arg Synthesis + /// @{ + + public: + /// MakeIndex - Get an index for the given string(s). + unsigned MakeIndex(llvm::StringRef String0) const; + unsigned MakeIndex(llvm::StringRef String0, llvm::StringRef String1) const; + + virtual const char *MakeArgString(llvm::StringRef Str) const; + + /// @} + }; + + /// DerivedArgList - An ordered collection of driver arguments, + /// whose storage may be in another argument list. + class DerivedArgList : public ArgList { + InputArgList &BaseArgs; + + /// The internal list of arguments. + arglist_type ActualArgs; + + /// The list of arguments we synthesized. + mutable arglist_type SynthesizedArgs; + + /// Is this only a proxy for the base ArgList? + bool OnlyProxy; + + public: + /// Construct a new derived arg list from \arg BaseArgs. + /// + /// \param OnlyProxy - If true, this is only a proxy for the base + /// list (to adapt the type), and it's Args list is unused. + DerivedArgList(InputArgList &BaseArgs, bool OnlyProxy); + ~DerivedArgList(); + + virtual const char *getArgString(unsigned Index) const { + return BaseArgs.getArgString(Index); + } + + /// @name Arg Synthesis + /// @{ + + virtual const char *MakeArgString(llvm::StringRef Str) const; + + /// MakeFlagArg - Construct a new FlagArg for the given option + /// \arg Id. + Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const; + + /// MakePositionalArg - Construct a new Positional arg for the + /// given option \arg Id, with the provided \arg Value. + Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) const; + + /// MakeSeparateArg - Construct a new Positional arg for the + /// given option \arg Id, with the provided \arg Value. + Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) const; + + /// MakeJoinedArg - Construct a new Positional arg for the + /// given option \arg Id, with the provided \arg Value. + Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) const; + + /// @} + }; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h new file mode 100644 index 0000000..0508213 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h @@ -0,0 +1,32 @@ +//===--- CC1AsOptions.h - Clang Assembler Options Table ---------*- 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_CC1ASOPTIONS_H +#define CLANG_DRIVER_CC1ASOPTIONS_H + +namespace clang { +namespace driver { + class OptTable; + +namespace cc1asoptions { + enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) OPT_##ID, +#include "clang/Driver/CC1AsOptions.inc" + LastOption +#undef OPTION + }; +} + + OptTable *createCC1AsOptTable(); +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td new file mode 100644 index 0000000..5c08dc6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td @@ -0,0 +1,71 @@ +//===--- CC1AsOptions.td - Options for clang -cc1as -----------------------===// +// +// 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 options accepted by clang -cc1as. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +//===----------------------------------------------------------------------===// +// Target Options +//===----------------------------------------------------------------------===// + +def triple : Separate<"-triple">, + HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; + +//===----------------------------------------------------------------------===// +// Language Options +//===----------------------------------------------------------------------===// + +def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, + HelpText<"Add directory to include search path">; +def n : Flag<"-n">, + HelpText<"Don't automatically start assembly file with a text section">; + +//===----------------------------------------------------------------------===// +// Frontend Options +//===----------------------------------------------------------------------===// + +def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; + +def filetype : Separate<"-filetype">, + HelpText<"Specify the output file type ('asm', 'null', or 'obj')">; + +def help : Flag<"-help">, + HelpText<"Print this help text">; +def _help : Flag<"--help">, Alias<help>; + +def version : Flag<"-version">, + HelpText<"Print the assembler version">; +def _version : Flag<"--version">, Alias<version>; + +// 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">; + +//===----------------------------------------------------------------------===// +// Transliterate Options +//===----------------------------------------------------------------------===// + +def output_asm_variant : Separate<"-output-asm-variant">, + HelpText<"Select the asm variant index to use for output">; +def show_encoding : Flag<"-show-encoding">, + HelpText<"Show instruction encoding information in transliterate mode">; +def show_inst : Flag<"-show-inst">, + HelpText<"Show internal instruction representation in transliterate mode">; + +//===----------------------------------------------------------------------===// +// Assemble Options +//===----------------------------------------------------------------------===// + +def relax_all : Flag<"-relax-all">, + HelpText<"Relax all fixups (for performance testing)">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h new file mode 100644 index 0000000..4a8bbe5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h @@ -0,0 +1,32 @@ +//===--- CC1Options.h - Clang CC1 Options Table -----------------*- 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_CC1OPTIONS_H +#define CLANG_DRIVER_CC1OPTIONS_H + +namespace clang { +namespace driver { + class OptTable; + +namespace cc1options { + enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) OPT_##ID, +#include "clang/Driver/CC1Options.inc" + LastOption +#undef OPTION + }; +} + + OptTable *createCC1OptTable(); +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td new file mode 100644 index 0000000..fd8322b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -0,0 +1,511 @@ +//===--- CC1Options.td - Options for clang -cc1 ---------------------------===// +// +// 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 options accepted by clang -cc1. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +//===----------------------------------------------------------------------===// +// Target Options +//===----------------------------------------------------------------------===// + +def target_abi : Separate<"-target-abi">, + HelpText<"Target a particular ABI type">; +def target_cpu : Separate<"-target-cpu">, + HelpText<"Target a specific cpu type">; +def target_feature : Separate<"-target-feature">, + HelpText<"Target specific attributes">; +def triple : Separate<"-triple">, + HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; +def triple_EQ : Joined<"-triple=">, Alias<triple>; + +//===----------------------------------------------------------------------===// +// Analyzer Options +//===----------------------------------------------------------------------===// + +def analysis_CFGDump : Flag<"-cfg-dump">, + HelpText<"Display Control-Flow Graphs">; +def analysis_CFGView : Flag<"-cfg-view">, + HelpText<"View Control-Flow Graphs using GraphViz">; +def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">, + HelpText<"Print results of live variable analysis">; +def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">, + HelpText<"Check code for LLVM codebase conventions (domain-specific)">; +def analysis_SecuritySyntacticChecks : Flag<"-analyzer-check-security-syntactic">, + HelpText<"Perform quick security checks that require no data flow">; +def analysis_WarnDeadStores : Flag<"-analyzer-check-dead-stores">, + HelpText<"Warn about stores to dead variables">; +def analysis_WarnUninitVals : Flag<"-warn-uninit-values">, + HelpText<"Warn about uses of uninitialized variables">; +def analysis_WarnObjCMethSigs : Flag<"-analyzer-check-objc-methodsigs">, + HelpText<"Warn about Objective-C method signatures with type incompatibilities">; +def analysis_WarnObjCDealloc : Flag<"-analyzer-check-objc-missing-dealloc">, + HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">; +def analysis_WarnObjCUnusedIvars : Flag<"-analyzer-check-objc-unused-ivars">, + HelpText<"Warn about private ivars that are never used">; +def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, + HelpText<"Run the [Core] Foundation reference count checker">; +def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, + HelpText<"Warn about unintended use of sizeof() on pointer expressions">; + +def analyzer_store : Separate<"-analyzer-store">, + HelpText<"Source Code Analysis - Abstract Memory Store Models">; +def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias<analyzer_store>; + +def analyzer_constraints : Separate<"-analyzer-constraints">, + HelpText<"Source Code Analysis - Symbolic Constraint Engines">; +def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">, + Alias<analyzer_constraints>; + +def analyzer_output : Separate<"-analyzer-output">, + HelpText<"Source Code Analysis - Output Options">; +def analyzer_output_EQ : Joined<"-analyzer-output=">, + Alias<analyzer_output>; + +def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">, + HelpText<"Force the static analyzer to analyze functions defined in header files">; +def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">, + HelpText<"Analyze the definitions of blocks in addition to functions">; +def analyzer_display_progress : Flag<"-analyzer-display-progress">, + HelpText<"Emit verbose output about the analyzer's progress">; +def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, + HelpText<"Use experimental path-sensitive checks">; +def analyzer_experimental_internal_checks : + Flag<"-analyzer-experimental-internal-checks">, + HelpText<"Use new default path-sensitive checks currently in testing">; +def analyze_function : Separate<"-analyze-function">, + HelpText<"Run analysis on specific function">; +def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>; +def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">, + HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; +def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">, + HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">; +def trim_egraph : Flag<"-trim-egraph">, + HelpText<"Only show error-related paths in the analysis graph">; +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_max_nodes : Separate<"-analyzer-max-nodes">, + HelpText<"The maximum number of nodes the analyzer can generate">; +def analyzer_max_loop : Separate<"-analyzer-max-loop">, + HelpText<"The maximum number of times the analyzer will go through a loop">; + +//===----------------------------------------------------------------------===// +// CodeGen Options +//===----------------------------------------------------------------------===// + +def disable_llvm_optzns : Flag<"-disable-llvm-optzns">, + HelpText<"Don't run LLVM optimization passes">; +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 dwarf_debug_flags : Separate<"-dwarf-debug-flags">, + HelpText<"The string to embed in the Dwarf debug flags record.">; +def g : Flag<"-g">, HelpText<"Generate source level debug information">; +def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, + HelpText<"Generate runtime checks for undefined behavior.">; +def fno_common : Flag<"-fno-common">, + HelpText<"Compile common globals like normal definitions">; +def no_implicit_float : Flag<"-no-implicit-float">, + HelpText<"Don't generate implicit floating point instructions (x86-only)">; +def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, + HelpText<"Disallow merging of constants.">; +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, + HelpText<"Do not emit code to make initialization of local statics thread safe">; +def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, + HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; +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 masm_verbose : Flag<"-masm-verbose">, + HelpText<"Generate verbose assembly output">; +def mcode_model : Separate<"-mcode-model">, + HelpText<"The code model to use">; +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 mfloat_abi : Separate<"-mfloat-abi">, + HelpText<"The float ABI to use">; +def mlimit_float_precision : Separate<"-mlimit-float-precision">, + HelpText<"Limit float precision to the given value">; +def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, + HelpText<"Do not put zero initialized data in the BSS">; +def msoft_float : Flag<"-msoft-float">, + HelpText<"Use software floating point">; +def mrelax_all : Flag<"-mrelax-all">, + HelpText<"Relax all machine instructions">; +def mrelocation_model : Separate<"-mrelocation-model">, + HelpText<"The relocation model to use">; +def munwind_tables : Flag<"-munwind-tables">, + HelpText<"Generate unwinding tables for all functions">; +def mconstructor_aliases : Flag<"-mconstructor-aliases">, + HelpText<"Emit complete constructors and destructors as aliases when possible">; +def O : Joined<"-O">, HelpText<"Optimization level">; +def Os : Flag<"-Os">, HelpText<"Optimize for size">; + +//===----------------------------------------------------------------------===// +// Dependency Output Options +//===----------------------------------------------------------------------===// + +def dependency_file : Separate<"-dependency-file">, + HelpText<"Filename (or -) to write dependency output to">; +def sys_header_deps : Flag<"-sys-header-deps">, + HelpText<"Include system headers in dependency output">; +def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; +def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; +def MP : Flag<"-MP">, + HelpText<"Create phony target for each dependency (other than main file)">; + +//===----------------------------------------------------------------------===// +// Diagnostic Options +//===----------------------------------------------------------------------===// + +def dump_build_information : Separate<"-dump-build-information">, + MetaVarName<"<filename>">, + HelpText<"output a dump of some build information to a file">; +def fno_show_column : Flag<"-fno-show-column">, + HelpText<"Do not include column number on diagnostics">; +def fno_show_source_location : Flag<"-fno-show-source-location">, + HelpText<"Do not include source location information with diagnostics">; +def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, + HelpText<"Do not include source line and caret with diagnostics">; +def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, + HelpText<"Do not include fixit information in diagnostics">; +def fdiagnostics_binary : Flag<"-fdiagnostics-binary">; +def w : Flag<"-w">, HelpText<"Suppress all warnings">; +def pedantic : Flag<"-pedantic">; +def pedantic_errors : Flag<"-pedantic-errors">; + +// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The +// driver has stripped off -Wa,foo etc. The driver has also translated -W to +// -Wextra, so we don't need to worry about it. +def W : Joined<"-W">; + +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, + HelpText<"Print source range spans in numeric form">; +def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, + HelpText<"Print diagnostic name with mappable diagnostics">; +def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, + HelpText<"Print diagnostic category">; + +def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, + HelpText<"Set the tab stop distance.">; +def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">; +def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of entries to print in a macro instantiation 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 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">, + HelpText<"Use colors in diagnostics">; +def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, + HelpText<"Silence ObjC rewriting warnings">; +def Wwrite_strings : Flag<"-Wwrite-strings">, + HelpText<"Add const qualifier to string literals">; +def verify : Flag<"-verify">, + HelpText<"Verify emitted diagnostics and warnings">; + +//===----------------------------------------------------------------------===// +// Frontend Options +//===----------------------------------------------------------------------===// + +// This isn't normally used, it is just here so we can parse a +// CompilerInvocation out of a driver-derived argument vector. +def cc1 : Flag<"-cc1">; + +def ast_merge : Separate<"-ast-merge">, + MetaVarName<"<ast file>">, + HelpText<"Merge the given AST file into the translation unit being compiled.">; +def code_completion_at : Separate<"-code-completion-at">, + MetaVarName<"<file>:<line>:<column>">, + HelpText<"Dump code-completion information at a location">; +def remap_file : Separate<"-remap-file">, + MetaVarName<"<from>;<to>">, + HelpText<"Replace the contents of the <from> file with the contents of the <to> file">; +def code_completion_at_EQ : Joined<"-code-completion-at=">, + Alias<code_completion_at>; +def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">, + HelpText<"Don't use the \"debug\" code-completion print">; +def code_completion_macros : Flag<"-code-completion-macros">, + HelpText<"Include macros in code-completion results">; +def code_completion_patterns : Flag<"-code-completion-patterns">, + HelpText<"Include code patterns in code-completion results">; +def disable_free : Flag<"-disable-free">, + HelpText<"Disable freeing of memory on exit">; +def help : Flag<"-help">, + HelpText<"Print this help text">; +def _help : Flag<"--help">, Alias<help>; +def x : Separate<"-x">, HelpText<"Input language type">; +def cxx_inheritance_view : Separate<"-cxx-inheritance-view">, + MetaVarName<"<class name>">, + HelpText<"View C++ inheritance for a specified class">; +def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; +def load : Separate<"-load">, MetaVarName<"<dsopath>">, + HelpText<"Load the named plugin (dynamic shared object)">; +def plugin : Separate<"-plugin">, + HelpText<"Use the named plugin action (use \"help\" to list available options)">; +def resource_dir : Separate<"-resource-dir">, + HelpText<"The directory which holds the compiler resource files">; +def version : Flag<"-version">, + HelpText<"Print the compiler version">; +def _version : Flag<"--version">, Alias<version>; + +def Action_Group : OptionGroup<"<action group>">; +let Group = Action_Group in { + +def Eonly : Flag<"-Eonly">, + HelpText<"Just run preprocessor, no output (for timings)">; +def E : Flag<"-E">, + HelpText<"Run preprocessor, emit preprocessed file">; +def dump_raw_tokens : Flag<"-dump-raw-tokens">, + HelpText<"Lex file in raw mode and dump raw tokens">; +def analyze : Flag<"-analyze">, + HelpText<"Run static analysis engine">; +def dump_tokens : Flag<"-dump-tokens">, + HelpText<"Run preprocessor, dump internal rep of tokens">; +def init_only : Flag<"-init-only">, + HelpText<"Only execute frontend initialization">; +def parse_noop : Flag<"-parse-noop">, + HelpText<"Run parser with noop callbacks (for timings)">; +def fsyntax_only : Flag<"-fsyntax-only">, + HelpText<"Run parser and perform semantic analysis">; +def fixit : Flag<"-fixit">, + HelpText<"Apply fix-it advice to the input source">; +def fixit_EQ : Joined<"-fixit=">, + HelpText<"Apply fix-it advice creating a file with the given suffix">; +def parse_print_callbacks : Flag<"-parse-print-callbacks">, + HelpText<"Run parser and print each callback invoked">; +def emit_html : Flag<"-emit-html">, + HelpText<"Output input source as HTML">; +def ast_print : Flag<"-ast-print">, + HelpText<"Build ASTs and then pretty-print them">; +def ast_print_xml : Flag<"-ast-print-xml">, + HelpText<"Build ASTs and then print them in XML format">; +def ast_dump : Flag<"-ast-dump">, + HelpText<"Build ASTs and then debug dump them">; +def ast_view : Flag<"-ast-view">, + HelpText<"Build ASTs and view them with GraphViz">; +def boostcon : Flag<"-boostcon">, + HelpText<"BoostCon workshop mode">; +def print_decl_contexts : Flag<"-print-decl-contexts">, + HelpText<"Print DeclContexts and their Decls">; +def emit_pth : Flag<"-emit-pth">, + HelpText<"Generate pre-tokenized header file">; +def emit_pch : Flag<"-emit-pch">, + HelpText<"Generate pre-compiled header file">; +def S : Flag<"-S">, + HelpText<"Emit native assembly code">; +def emit_llvm : Flag<"-emit-llvm">, + HelpText<"Build ASTs then convert to LLVM, emit .ll file">; +def emit_llvm_bc : Flag<"-emit-llvm-bc">, + HelpText<"Build ASTs then convert to LLVM, emit .bc file">; +def emit_llvm_only : Flag<"-emit-llvm-only">, + HelpText<"Build ASTs and convert to LLVM, discarding output">; +def emit_codegen_only : Flag<"-emit-codegen-only">, + HelpText<"Generate machine code, but discard output">; +def emit_obj : Flag<"-emit-obj">, + HelpText<"Emit native object files">; +def rewrite_test : Flag<"-rewrite-test">, + HelpText<"Rewriter playground">; +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 relocatable_pch : Flag<"-relocatable-pch">, + HelpText<"Whether to build a relocatable precompiled header">; +def print_stats : Flag<"-print-stats">, + HelpText<"Print performance metrics and statistics">; +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">; + +// 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">; + +//===----------------------------------------------------------------------===// +// Language Options +//===----------------------------------------------------------------------===// + +def fno_builtin : Flag<"-fno-builtin">, + HelpText<"Disable implicit builtin knowledge of functions">; +def faltivec : Flag<"-faltivec">, + HelpText<"Enable AltiVec vector initializer syntax">; +def fno_access_control : Flag<"-fno-access-control">, + HelpText<"Disable C++ access control">; +def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, + HelpText<"Don't assume that C++'s global operator new can't alias any pointer">; +def fgnu_keywords : Flag<"-fgnu-keywords">, + HelpText<"Allow GNU-extension keywords regardless of language standard">; +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">, + HelpText<"Allow '$' in identifiers">; +def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, + HelpText<"Disallow '$' in identifiers">; +def femit_all_decls : Flag<"-femit-all-decls">, + HelpText<"Emit all declarations, even if unused">; +def fblocks : Flag<"-fblocks">, + HelpText<"enable the 'blocks' language feature">; +def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; +def fexceptions : Flag<"-fexceptions">, + HelpText<"Enable support for exception handling">; +def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, + HelpText<"Use SjLj style exceptions">; +def ffreestanding : Flag<"-ffreestanding">, + HelpText<"Assert that the compilation takes place in a freestanding environment">; +def fgnu_runtime : Flag<"-fgnu-runtime">, + HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; +def std_EQ : Joined<"-std=">, + HelpText<"Language standard to compile for">; +def fmath_errno : Flag<"-fmath-errno">, + HelpText<"Require math functions to indicate errors by setting errno">; +def fms_extensions : Flag<"-fms-extensions">, + HelpText<"Accept some non-standard constructs used in Microsoft header files ">; +def main_file_name : Separate<"-main-file-name">, + HelpText<"Main file name to use for debug info">; +def fno_elide_constructors : Flag<"-fno-elide-constructors">, + HelpText<"Disable C++ copy constructor elision">; +def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, + HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">; +def fno_operator_names : Flag<"-fno-operator-names">, + HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; +def fno_signed_char : Flag<"-fno-signed-char">, + HelpText<"Char is unsigned">; +def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, + HelpText<"Don't use __cxa_atexit for calling destructors">; +def fconstant_string_class : Separate<"-fconstant-string-class">, + MetaVarName<"<class name>">, + HelpText<"Specify the class to use for constant Objective-C string objects.">; +def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, + HelpText<"Enable creation of CodeFoundation-type constant strings">; +def fobjc_gc : Flag<"-fobjc-gc">, + HelpText<"Enable Objective-C garbage collection">; +def fobjc_gc_only : Flag<"-fobjc-gc-only">, + HelpText<"Use GC exclusively for Objective-C related memory management">; +def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">, + HelpText<"Objective-C dispatch method to use">; +def print_ivar_layout : Flag<"-print-ivar-layout">, + HelpText<"Enable Objective-C Ivar layout bitmap print trace">; +def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, + HelpText<"enable objective-c's nonfragile abi">; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, + HelpText<"enable objective-c's enhanced nonfragile abi">; +def ftrapv : Flag<"-ftrapv">, + HelpText<"Trap on integer overflow">; +def pic_level : Separate<"-pic-level">, + HelpText<"Value for __PIC__">; +def pthread : Flag<"-pthread">, + HelpText<"Support POSIX threads in generated code">; +def fpascal_strings : Flag<"-fpascal-strings">, + HelpText<"Recognize and construct Pascal-style string literals">; +def fno_rtti : Flag<"-fno-rtti">, + HelpText<"Disable generation of rtti information">; +def fshort_wchar : Flag<"-fshort-wchar">, + HelpText<"Force wchar_t to be a short unsigned int">; +def static_define : Flag<"-static-define">, + HelpText<"Should __STATIC__ be defined">; +def stack_protector : Separate<"-stack-protector">, + HelpText<"Enable stack protectors">; +def fvisibility : Separate<"-fvisibility">, + HelpText<"Default symbol visibility">; +def ftemplate_depth : Separate<"-ftemplate-depth">, + HelpText<"Maximum depth of recursive template instantiation">; +def trigraphs : Flag<"-trigraphs">, + HelpText<"Process trigraph sequences">; +def fwritable_strings : Flag<"-fwritable-strings">, + HelpText<"Store string literals as writable data">; +def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, + HelpText<"Ignore bit-field types when aligning structures">; + +//===----------------------------------------------------------------------===// +// Header Search Options +//===----------------------------------------------------------------------===// + +def nostdinc : Flag<"-nostdinc">, + HelpText<"Disable standard #include directories">; +def nostdincxx : Flag<"-nostdinc++">, + HelpText<"Disable standard #include directories for the C++ standard library">; +def nobuiltininc : Flag<"-nobuiltininc">, + HelpText<"Disable builtin #include directories">; +def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, + HelpText<"Add directory to framework include search path">; +def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, + HelpText<"Add directory to include search path">; +def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">, + HelpText<"Add directory to AFTER include search path">; +def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, + HelpText<"Add directory to QUOTE include search path">; +def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, + HelpText<"Add directory to SYSTEM include search path">; +def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">, + HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; +def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">, + HelpText<"Set directory to SYSTEM include search path with prefix">; +def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, + MetaVarName<"<dir>">, + HelpText<"Set directory to include search path with prefix">; +def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">, + HelpText<"Set the system root directory (usually /)">; +def v : Flag<"-v">, HelpText<"Enable verbose output">; + +//===----------------------------------------------------------------------===// +// Preprocessor Options +//===----------------------------------------------------------------------===// + +def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">, + HelpText<"Predefine the specified macro">; +def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">, + HelpText<"Include file before parsing">; +def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">, + HelpText<"Include macros from file before parsing">; +def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">, + HelpText<"Include precompiled header file">; +def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">, + HelpText<"Include file before parsing">; +def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">, + HelpText<"Use specified token cache file">; +def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">, + HelpText<"Undefine the specified macro">; +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">; + +//===----------------------------------------------------------------------===// +// Preprocessed Output Options +//===----------------------------------------------------------------------===// + +def P : Flag<"-P">, + HelpText<"Disable linemarker output in -E mode">; +def C : Flag<"-C">, + HelpText<"Enable comment output in -E mode">; +def CC : Flag<"-CC">, + HelpText<"Enable comment output in -E mode, even from macro expansions">; +def dM : Flag<"-dM">, + HelpText<"Print macro definitions in -E mode instead of normal output">; +def dD : Flag<"-dD">, + HelpText<"Print macro definitions in -E mode in addition to normal output">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CMakeLists.txt b/contrib/llvm/tools/clang/include/clang/Driver/CMakeLists.txt new file mode 100644 index 0000000..99be53f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_TARGET_DEFINITIONS Options.td) +tablegen(Options.inc + -gen-opt-parser-defs) +add_custom_target(ClangDriverOptions + DEPENDS Options.inc) + +set(LLVM_TARGET_DEFINITIONS CC1Options.td) +tablegen(CC1Options.inc + -gen-opt-parser-defs) +add_custom_target(ClangCC1Options + DEPENDS CC1Options.inc) + +set(LLVM_TARGET_DEFINITIONS CC1AsOptions.td) +tablegen(CC1AsOptions.inc + -gen-opt-parser-defs) +add_custom_target(ClangCC1AsOptions + DEPENDS CC1AsOptions.inc) diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h new file mode 100644 index 0000000..56786a7 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h @@ -0,0 +1,136 @@ +//===--- Compilation.h - Compilation Task Data Structure --------*- 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_COMPILATION_H_ +#define CLANG_DRIVER_COMPILATION_H_ + +#include "clang/Driver/Job.h" +#include "clang/Driver/Util.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { +namespace driver { + class DerivedArgList; + class Driver; + class InputArgList; + class JobList; + class ToolChain; + +/// Compilation - A set of tasks to perform for a single driver +/// invocation. +class Compilation { + /// The driver we were created by. + const Driver &TheDriver; + + /// The default tool chain. + const ToolChain &DefaultToolChain; + + /// The original (untranslated) input argument list. + InputArgList *Args; + + /// The list of actions. + ActionList Actions; + + /// The root list of jobs. + JobList Jobs; + + /// Cache of translated arguments for a particular tool chain. + llvm::DenseMap<std::pair<const ToolChain*, const char*>, + DerivedArgList*> TCArgs; + + /// Temporary files which should be removed on exit. + ArgStringList TempFiles; + + /// Result files which should be removed on failure. + ArgStringList ResultFiles; + +public: + Compilation(const Driver &D, const ToolChain &DefaultToolChain, + InputArgList *Args); + ~Compilation(); + + const Driver &getDriver() const { return TheDriver; } + + const ToolChain &getDefaultToolChain() const { return DefaultToolChain; } + + const InputArgList &getArgs() const { return *Args; } + + ActionList &getActions() { return Actions; } + const ActionList &getActions() const { return Actions; } + + JobList &getJobs() { return Jobs; } + const JobList &getJobs() const { return Jobs; } + + const ArgStringList &getTempFiles() const { return TempFiles; } + + const ArgStringList &getResultFiles() const { return ResultFiles; } + + /// getArgsForToolChain - Return the derived argument list for the + /// tool chain \arg TC (or the default tool chain, if TC is not + /// specified). + /// + /// \param BoundArch - The bound architecture name, or 0. + const DerivedArgList &getArgsForToolChain(const ToolChain *TC, + const char *BoundArch); + + /// addTempFile - Add a file to remove on exit, and returns its + /// argument. + const char *addTempFile(const char *Name) { + TempFiles.push_back(Name); + return Name; + } + + /// addResultFile - Add a file to remove on failure, and returns its + /// argument. + const char *addResultFile(const char *Name) { + ResultFiles.push_back(Name); + return Name; + } + + /// CleanupFileList - Remove the files in the given list. + /// + /// \param IssueErrors - Report failures as errors. + /// \return Whether all files were removed successfully. + bool CleanupFileList(const ArgStringList &Files, + bool IssueErrors=false) const; + + /// PrintJob - Print one job in -### format. + /// + /// \param OS - The stream to print on. + /// \param J - The job to print. + /// \param Terminator - A string to print at the end of the line. + /// \param Quote - Should separate arguments be quoted. + void PrintJob(llvm::raw_ostream &OS, const Job &J, + const char *Terminator, bool Quote) const; + + /// ExecuteCommand - Execute an actual command. + /// + /// \param FailingCommand - For non-zero results, this will be set to the + /// Command which failed, if any. + /// \return The result code of the subprocess. + int ExecuteCommand(const Command &C, const Command *&FailingCommand) const; + + /// ExecuteJob - Execute a single job. + /// + /// \param FailingCommand - For non-zero results, this will be set to the + /// Command which failed. + /// \return The accumulated result code of the job. + int ExecuteJob(const Job &J, const Command *&FailingCommand) const; +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h new file mode 100644 index 0000000..90c3a0d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h @@ -0,0 +1,318 @@ +//===--- Driver.h - Clang GCC Compatible Driver -----------------*- 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_DRIVER_H_ +#define CLANG_DRIVER_DRIVER_H_ + +#include "clang/Basic/Diagnostic.h" + +#include "clang/Driver/Phases.h" +#include "clang/Driver/Util.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo + // lands. +#include <list> +#include <set> +#include <string> + +namespace llvm { + class raw_ostream; +} +namespace clang { +namespace driver { + class Action; + class ArgList; + class Compilation; + class HostInfo; + class InputArgList; + class InputInfo; + class JobAction; + class OptTable; + class PipedJob; + class ToolChain; + +/// Driver - Encapsulate logic for constructing compilation processes +/// from a set of gcc-driver-like command line arguments. +class Driver { + OptTable *Opts; + + Diagnostic &Diags; + +public: + // Diag - Forwarding function for diagnostics. + DiagnosticBuilder Diag(unsigned DiagID) const { + return Diags.Report(DiagID); + } + + // FIXME: Privatize once interface is stable. +public: + /// The name the driver was invoked as. + std::string Name; + + /// The path the driver executable was in, as invoked from the + /// command line. + std::string Dir; + + /// The path to the compiler resource directory. + std::string ResourceDir; + + /// A prefix directory used to emulated a limited subset of GCC's '-Bprefix' + /// functionality. + /// FIXME: This type of customization should be removed in favor of the + /// universal driver when it is ready. + std::string PrefixDir; + + /// Default host triple. + std::string DefaultHostTriple; + + /// Default name for linked images (e.g., "a.out"). + std::string DefaultImageName; + + /// Driver title to use with help. + std::string DriverTitle; + + /// Host information for the platform the driver is running as. This + /// will generally be the actual host platform, but not always. + const HostInfo *Host; + + /// Information about the host which can be overriden by the user. + std::string HostBits, HostMachine, HostSystem, HostRelease; + + /// Name to use when calling the generic gcc. + std::string CCCGenericGCCName; + + /// The file to log CC_PRINT_OPTIONS output to, if enabled. + const char *CCPrintOptionsFilename; + + /// Whether the driver should follow g++ like behavior. + unsigned CCCIsCXX : 1; + + /// Echo commands while executing (in -v style). + unsigned CCCEcho : 1; + + /// Only print tool bindings, don't build any jobs. + unsigned CCCPrintBindings : 1; + + /// Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to + /// CCPrintOptionsFilename or to stderr. + unsigned CCPrintOptions : 1; + +private: + /// Whether to check that input files exist when constructing compilation + /// jobs. + unsigned CheckInputsExist : 1; + + /// Use the clang compiler where possible. + unsigned CCCUseClang : 1; + + /// Use clang for handling C++ and Objective-C++ inputs. + unsigned CCCUseClangCXX : 1; + + /// Use clang as a preprocessor (clang's preprocessor will still be + /// used where an integrated CPP would). + unsigned CCCUseClangCPP : 1; + +public: + /// Use lazy precompiled headers for PCH support. + unsigned CCCUsePCH : 1; + +private: + /// Only use clang for the given architectures (only used when + /// non-empty). + std::set<llvm::Triple::ArchType> CCCClangArchs; + + /// Certain options suppress the 'no input files' warning. + bool SuppressMissingInputWarning : 1; + + std::list<std::string> TempFiles; + std::list<std::string> ResultFiles; + +public: + Driver(llvm::StringRef _Name, llvm::StringRef _Dir, + llvm::StringRef _DefaultHostTriple, + llvm::StringRef _DefaultImageName, + bool IsProduction, bool CXXIsProduction, + Diagnostic &_Diags); + ~Driver(); + + /// @name Accessors + /// @{ + + const OptTable &getOpts() const { return *Opts; } + + const Diagnostic &getDiags() const { return Diags; } + + bool getCheckInputsExist() const { return CheckInputsExist; } + + void setCheckInputsExist(bool Value) { CheckInputsExist = Value; } + + const std::string &getTitle() { return DriverTitle; } + void setTitle(std::string Value) { DriverTitle = Value; } + + /// @} + /// @name Primary Functionality + /// @{ + + /// BuildCompilation - Construct a compilation object for a command + /// line argument vector. + /// + /// \return A compilation, or 0 if none was built for the given + /// argument vector. A null return value does not necessarily + /// indicate an error condition, the diagnostics should be queried + /// to determine if an error occurred. + Compilation *BuildCompilation(int argc, const char **argv); + + /// @name Driver Steps + /// @{ + + /// ParseArgStrings - Parse the given list of strings into an + /// ArgList. + InputArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd); + + /// BuildActions - Construct the list of actions to perform for the + /// given arguments, which are only done for a single architecture. + /// + /// \param Args - The input arguments. + /// \param Actions - The list to store the resulting actions onto. + void BuildActions(const ArgList &Args, ActionList &Actions) const; + + /// BuildUniversalActions - Construct the list of actions to perform + /// for the given arguments, which may require a universal build. + /// + /// \param Args - The input arguments. + /// \param Actions - The list to store the resulting actions onto. + void BuildUniversalActions(const ArgList &Args, ActionList &Actions) const; + + /// BuildJobs - Bind actions to concrete tools and translate + /// arguments to form the list of jobs to run. + /// + /// \arg C - The compilation that is being built. + void BuildJobs(Compilation &C) const; + + /// ExecuteCompilation - Execute the compilation according to the command line + /// arguments and return an appropriate exit code. + /// + /// This routine handles additional processing that must be done in addition + /// to just running the subprocesses, for example reporting errors, removing + /// temporary files, etc. + int ExecuteCompilation(const Compilation &C) const; + + /// @} + /// @name Helper Methods + /// @{ + + /// PrintActions - Print the list of actions. + void PrintActions(const Compilation &C) const; + + /// PrintHelp - Print the help text. + /// + /// \param ShowHidden - Show hidden options. + void PrintHelp(bool ShowHidden) const; + + /// PrintOptions - Print the list of arguments. + void PrintOptions(const ArgList &Args) const; + + /// PrintVersion - Print the driver version. + void PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const; + + /// GetFilePath - Lookup \arg Name in the list of file search paths. + /// + /// \arg TC - The tool chain for additional information on + /// directories to search. + // + // FIXME: This should be in CompilationInfo. + std::string GetFilePath(const char *Name, const ToolChain &TC) const; + + /// GetProgramPath - Lookup \arg Name in the list of program search + /// paths. + /// + /// \arg TC - The provided tool chain for additional information on + /// directories to search. + /// + /// \arg WantFile - False when searching for an executable file, otherwise + /// true. Defaults to false. + // + // FIXME: This should be in CompilationInfo. + std::string GetProgramPath(const char *Name, const ToolChain &TC, + bool WantFile = false) const; + + /// HandleImmediateArgs - Handle any arguments which should be + /// treated before building actions or binding tools. + /// + /// \return Whether any compilation should be built for this + /// invocation. + bool HandleImmediateArgs(const Compilation &C); + + /// ConstructAction - Construct the appropriate action to do for + /// \arg Phase on the \arg Input, taking in to account arguments + /// like -fsyntax-only or --analyze. + Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase, + Action *Input) const; + + + /// BuildJobsForAction - Construct the jobs to perform for the + /// action \arg A. + void BuildJobsForAction(Compilation &C, + const Action *A, + const ToolChain *TC, + const char *BoundArch, + bool CanAcceptPipe, + bool AtTopLevel, + const char *LinkingOutput, + InputInfo &Result) const; + + /// GetNamedOutputPath - Return the name to use for the output of + /// the action \arg JA. The result is appended to the compilation's + /// list of temporary or result files, as appropriate. + /// + /// \param C - The compilation. + /// \param JA - The action of interest. + /// \param BaseInput - The original input file that this action was + /// triggered by. + /// \param AtTopLevel - Whether this is a "top-level" action. + const char *GetNamedOutputPath(Compilation &C, + const JobAction &JA, + const char *BaseInput, + bool AtTopLevel) const; + + /// GetTemporaryPath - Return the pathname of a temporary file to + /// use as part of compilation; the file will have the given suffix. + /// + /// GCC goes to extra lengths here to be a bit more robust. + std::string GetTemporaryPath(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, + const llvm::Triple &ArchName) const; + + /// @} + + /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and + /// return the grouped values as integers. Numbers which are not + /// provided are set to 0. + /// + /// \return True if the entire string was parsed (9.2), or all + /// groups were parsed (10.3.5extrastuff). HadExtra is true if all + /// groups were parsed but extra characters remain at the end. + static bool GetReleaseVersion(const char *Str, unsigned &Major, + unsigned &Minor, unsigned &Micro, + bool &HadExtra); +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h new file mode 100644 index 0000000..c20d807b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticDriver.h - Diagnostics for libdriver ---------*- 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_DRIVERDIAGNOSTIC_H +#define LLVM_CLANG_DRIVERDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define DRIVERSTART +#include "clang/Basic/DiagnosticDriverKinds.inc" +#undef DIAG + NUM_BUILTIN_DRIVER_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h b/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h new file mode 100644 index 0000000..ca1ee9a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h @@ -0,0 +1,91 @@ +//===--- 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 "clang/Driver/Types.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; + + /// lookupTypeForExtension - Return the default language type to use for the + /// given extension. + virtual types::ID lookupTypeForExtension(const char *Ext) 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 *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 *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 new file mode 100644 index 0000000..5a789fb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h @@ -0,0 +1,157 @@ +//===--- Job.h - Commands to Execute ----------------------------*- 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_JOB_H_ +#define CLANG_DRIVER_JOB_H_ + +#include "clang/Driver/Util.h" +#include "llvm/ADT/SmallVector.h" + +#include "llvm/Support/Casting.h" +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; + +namespace clang { +namespace driver { +class Command; +class Tool; + +class Job { +public: + enum JobClass { + CommandClass, + PipedJobClass, + JobListClass + }; + +private: + JobClass Kind; + +protected: + Job(JobClass _Kind) : Kind(_Kind) {} +public: + virtual ~Job(); + + JobClass getKind() const { return Kind; } + + /// addCommand - Append a command to the current job, which must be + /// either a piped job or a job list. + void addCommand(Command *C); + + static bool classof(const Job *) { return true; } +}; + + /// Command - An executable path/name and argument vector to + /// execute. +class Command : public Job { + /// Source - The action which caused the creation of this job. + const Action &Source; + + /// Tool - The tool which caused the creation of this job. + const Tool &Creator; + + /// The executable to run. + const char *Executable; + + /// The list of program arguments (not including the implicit first + /// argument, which will be the executable). + ArgStringList Arguments; + +public: + Command(const Action &_Source, const Tool &_Creator, const char *_Executable, + const ArgStringList &_Arguments); + + /// getSource - Return the Action which caused the creation of this job. + const Action &getSource() const { return Source; } + + /// getCreator - Return the Tool which caused the creation of this job. + const Tool &getCreator() const { return Creator; } + + const char *getExecutable() const { return Executable; } + + const ArgStringList &getArguments() const { return Arguments; } + + static bool classof(const Job *J) { + return J->getKind() == CommandClass; + } + static bool classof(const Command *) { return true; } +}; + + /// PipedJob - A list of Commands which should be executed together + /// with their standard inputs and outputs connected. +class PipedJob : public Job { +public: + typedef llvm::SmallVector<Command*, 4> list_type; + typedef list_type::size_type size_type; + typedef list_type::iterator iterator; + typedef list_type::const_iterator const_iterator; + +private: + list_type Commands; + +public: + PipedJob(); + virtual ~PipedJob(); + + /// Add a command to the piped job (taking ownership). + void addCommand(Command *C) { Commands.push_back(C); } + + const list_type &getCommands() const { return Commands; } + + size_type size() const { return Commands.size(); } + iterator begin() { return Commands.begin(); } + const_iterator begin() const { return Commands.begin(); } + iterator end() { return Commands.end(); } + const_iterator end() const { return Commands.end(); } + + static bool classof(const Job *J) { + return J->getKind() == PipedJobClass; + } + static bool classof(const PipedJob *) { return true; } +}; + + /// JobList - A sequence of jobs to perform. +class JobList : public Job { +public: + typedef llvm::SmallVector<Job*, 4> list_type; + typedef list_type::size_type size_type; + typedef list_type::iterator iterator; + typedef list_type::const_iterator const_iterator; + +private: + list_type Jobs; + +public: + JobList(); + virtual ~JobList(); + + /// Add a job to the list (taking ownership). + void addJob(Job *J) { Jobs.push_back(J); } + + const list_type &getJobs() const { return Jobs; } + + size_type size() const { return Jobs.size(); } + iterator begin() { return Jobs.begin(); } + const_iterator begin() const { return Jobs.begin(); } + iterator end() { return Jobs.end(); } + const_iterator end() const { return Jobs.end(); } + + static bool classof(const Job *J) { + return J->getKind() == JobListClass; + } + static bool classof(const JobList *) { return true; } +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Makefile b/contrib/llvm/tools/clang/include/clang/Driver/Makefile new file mode 100644 index 0000000..b462aaa --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Makefile @@ -0,0 +1,18 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = Options.inc CC1Options.inc CC1AsOptions.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang Driver Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< + +$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang CC1 Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< + +$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td OptParser.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang CC1 Assembler Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td new file mode 100644 index 0000000..a9f4289 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td @@ -0,0 +1,135 @@ +//===--- OptParser.td - Common Option Parsing Interfaces ------------------===// +// +// 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 common interfaces used by the option parsing TableGen +// backend. +// +//===----------------------------------------------------------------------===// + +// Define the kinds of options. + +class OptionKind<string name, int predecence = 0, bit sentinel = 0> { + string Name = name; + // The kind precedence, kinds with lower precedence are matched first. + int Precedence = predecence; + // Indicate a sentinel option. + bit Sentinel = sentinel; +} + +// An option group. +def KIND_GROUP : OptionKind<"Group">; +// The input option kind. +def KIND_INPUT : OptionKind<"Input", 1, 1>; +// The unknown option kind. +def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>; +// A flag with no values. +def KIND_FLAG : OptionKind<"Flag">; +// An option which prefixes its (single) value. +def KIND_JOINED : OptionKind<"Joined", 1>; +// An option which is followed by its value. +def KIND_SEPARATE : OptionKind<"Separate">; +// An option followed by its values, which are separated by commas. +def KIND_COMMAJOINED : OptionKind<"CommaJoined">; +// An option which is which takes multiple (separate) arguments. +def KIND_MULTIARG : OptionKind<"MultiArg">; +// An option which is either joined to its (non-empty) value, or followed by its +// value. +def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">; +// An option which is both joined to its (first) value, and followed by its +// (second) value. +def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">; + +// Define the option flags. + +class OptionFlag {} + +// DriverOption - The option is a "driver" option, and should not be forwarded +// to gcc. +def DriverOption : OptionFlag; + +// LinkerInput - The option is a linker input. +def LinkerInput : OptionFlag; + +// NoArgumentUnused - Don't report argument unused warnings for this option; this +// is useful for options like -static or -dynamic which a user may always end up +// passing, even if the platform defaults to (or only supports) that option. +def NoArgumentUnused : OptionFlag; + +// RenderAsInput - The option should not render the name when rendered as an +// input (i.e., the option is rendered as values). +def RenderAsInput : OptionFlag; + +// RenderJoined - The option should be rendered joined, even if separate (only +// sensible on single value separate options). +def RenderJoined : OptionFlag; + +// RenderSeparate - The option should be rendered separately, even if joined +// (only sensible on joined options). +def RenderSeparate : OptionFlag; + +// Unsupported - The option is unsupported, and the driver will reject command +// lines that use it. +def Unsupported : OptionFlag; + +// HelpHidden - The option should not be displayed in --help, even if it has +// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp +// arguments to implement hidden help groups. +def HelpHidden : OptionFlag; + +// Define the option group class. + +class OptionGroup<string name> { + string EnumName = ?; // Uses the def name if undefined. + string Name = name; + string HelpText = ?; + OptionGroup Group = ?; +} + +// Define the option class. + +class Option<string name, OptionKind kind> { + string EnumName = ?; // Uses the def name if undefined. + string Name = name; + OptionKind Kind = kind; + // Used by MultiArg option kind. + int NumArgs = 0; + string HelpText = ?; + string MetaVarName = ?; + list<OptionFlag> Flags = []; + OptionGroup Group = ?; + Option Alias = ?; +} + +// Helpers for defining options. + +class Flag<string name> : Option<name, KIND_FLAG>; +class Joined<string name> : Option<name, KIND_JOINED>; +class Separate<string name> : Option<name, KIND_SEPARATE>; +class CommaJoined<string name> : Option<name, KIND_COMMAJOINED>; +class MultiArg<string name, int numargs> : Option<name, KIND_MULTIARG> { + int NumArgs = numargs; +} +class JoinedOrSeparate<string name> : Option<name, KIND_JOINED_OR_SEPARATE>; +class JoinedAndSeparate<string name> : Option<name, KIND_JOINED_AND_SEPARATE>; + +// Mix-ins for adding optional attributes. + +class Alias<Option alias> { Option Alias = alias; } +class EnumName<string name> { string EnumName = name; } +class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; } +class Group<OptionGroup group> { OptionGroup Group = group; } +class HelpText<string text> { string HelpText = text; } +class MetaVarName<string name> { string MetaVarName = name; } + +// Predefined options. + +// FIXME: Have generator validate that these appear in correct position (and +// aren't duplicated). +def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>; +def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h b/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h new file mode 100644 index 0000000..bb1cd17 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h @@ -0,0 +1,39 @@ +//===--- OptSpecifier.h - Option Specifiers ---------------------*- 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_OPTSPECIFIER_H +#define CLANG_DRIVER_OPTSPECIFIER_H + +namespace clang { +namespace driver { + class Option; + + /// OptSpecifier - Wrapper class for abstracting references to option IDs. + class OptSpecifier { + unsigned ID; + + private: + explicit OptSpecifier(bool); // DO NOT IMPLEMENT + + public: + OptSpecifier() : ID(0) {} + /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} + /*implicit*/ OptSpecifier(const Option *Opt); + + bool isValid() const { return ID != 0; } + + unsigned getID() const { return ID; } + + bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } + bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); } + }; +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h new file mode 100644 index 0000000..edae75c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h @@ -0,0 +1,188 @@ +//===--- OptTable.h - Option Table ------------------------------*- 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_OPTTABLE_H +#define CLANG_DRIVER_OPTTABLE_H + +#include "clang/Driver/OptSpecifier.h" +#include <cassert> + +namespace llvm { + class raw_ostream; +} + +namespace clang { +namespace driver { +namespace options { + enum DriverFlag { + DriverOption = (1 << 0), + HelpHidden = (1 << 1), + LinkerInput = (1 << 2), + NoArgumentUnused = (1 << 3), + RenderAsInput = (1 << 4), + RenderJoined = (1 << 5), + RenderSeparate = (1 << 6), + Unsupported = (1 << 7) + }; +} + + class Arg; + class InputArgList; + class Option; + + /// OptTable - Provide access to the Option info table. + /// + /// The OptTable class provides a layer of indirection which allows Option + /// instance to be created lazily. In the common case, only a few options will + /// be needed at runtime; the OptTable class maintains enough information to + /// parse command lines without instantiating Options, while letting other + /// parts of the driver still use Option instances where convenient. + class OptTable { + public: + /// Info - Entry for a single option instance in the option data table. + struct Info { + const char *Name; + const char *HelpText; + const char *MetaVar; + unsigned char Kind; + unsigned char Flags; + unsigned char Param; + unsigned short GroupID; + unsigned short AliasID; + }; + + private: + /// The static option information table. + const Info *OptionInfos; + unsigned NumOptionInfos; + + /// The lazily constructed options table, indexed by option::ID - 1. + mutable Option **Options; + + /// Prebound input option instance. + const Option *TheInputOption; + + /// Prebound unknown option instance. + const Option *TheUnknownOption; + + /// The index of the first option which can be parsed (i.e., is not a + /// special option like 'input' or 'unknown', and is not an option group). + unsigned FirstSearchableIndex; + + private: + const Info &getInfo(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID."); + return OptionInfos[id - 1]; + } + + Option *CreateOption(unsigned id) const; + + protected: + OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); + public: + ~OptTable(); + + /// getNumOptions - Return the total number of option classes. + unsigned getNumOptions() const { return NumOptionInfos; } + + /// getOption - Get the given \arg id's Option instance, lazily creating it + /// if necessary. + /// + /// \return The option, or null for the INVALID option id. + const Option *getOption(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + if (id == 0) + return 0; + + assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); + Option *&Entry = Options[id - 1]; + if (!Entry) + Entry = CreateOption(id); + return Entry; + } + + /// getOptionName - Lookup the name of the given option. + const char *getOptionName(OptSpecifier id) const { + return getInfo(id).Name; + } + + /// getOptionKind - Get the kind of the given option. + unsigned getOptionKind(OptSpecifier id) const { + return getInfo(id).Kind; + } + + /// getOptionGroupID - Get the group id for the given option. + unsigned getOptionGroupID(OptSpecifier id) const { + return getInfo(id).GroupID; + } + + /// isOptionHelpHidden - Should the help for the given option be hidden by + /// default. + bool isOptionHelpHidden(OptSpecifier id) const { + return getInfo(id).Flags & options::HelpHidden; + } + + /// getOptionHelpText - Get the help text to use to describe this option. + const char *getOptionHelpText(OptSpecifier id) const { + return getInfo(id).HelpText; + } + + /// getOptionMetaVar - Get the meta-variable name to use when describing + /// this options values in the help text. + const char *getOptionMetaVar(OptSpecifier id) const { + return getInfo(id).MetaVar; + } + + /// ParseOneArg - Parse a single argument; returning the new argument and + /// updating Index. + /// + /// \param [in] [out] Index - The current parsing position in the argument + /// string list; on return this will be the index of the next argument + /// string to parse. + /// + /// \return - The parsed argument, or 0 if the argument is missing values + /// (in which case Index still points at the conceptual next argument string + /// to parse). + Arg *ParseOneArg(const InputArgList &Args, unsigned &Index) const; + + /// ParseArgs - Parse an list of arguments into an InputArgList. + /// + /// The resulting InputArgList will reference the strings in [ArgBegin, + /// ArgEnd), and their lifetime should extend past that of the returned + /// InputArgList. + /// + /// The only error that can occur in this routine is if an argument is + /// missing values; in this case \arg MissingArgCount will be non-zero. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// \param ArgEnd - The end of the argument vector. + /// \param MissingArgIndex - On error, the index of the option which could + /// not be parsed. + /// \param MissingArgCount - On error, the number of missing options. + /// \return - An InputArgList; on error this will contain all the options + /// which could be parsed. + InputArgList *ParseArgs(const char **ArgBegin, + const char **ArgEnd, + unsigned &MissingArgIndex, + unsigned &MissingArgCount) const; + + /// PrintHelp - Render the help text for an option table. + /// + /// \param OS - The stream to write the help text to. + /// \param Name - The name to use in the usage line. + /// \param Title - The title to use in the usage line. + /// \param ShowHidden - Whether help-hidden arguments should be shown. + void PrintHelp(llvm::raw_ostream &OS, const char *Name, + const char *Title, bool ShowHidden = false) const; + }; +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Option.h b/contrib/llvm/tools/clang/include/clang/Driver/Option.h new file mode 100644 index 0000000..08b94b1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Option.h @@ -0,0 +1,311 @@ +//===--- Option.h - Abstract Driver Options ---------------------*- 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_OPTION_H_ +#define CLANG_DRIVER_OPTION_H_ + +#include "clang/Driver/OptSpecifier.h" +#include "llvm/Support/Casting.h" +using llvm::isa; +using llvm::cast; +using llvm::cast_or_null; +using llvm::dyn_cast; +using llvm::dyn_cast_or_null; + +namespace clang { +namespace driver { + class Arg; + class InputArgList; + class OptionGroup; + + /// Option - Abstract representation for a single form of driver + /// argument. + /// + /// An Option class represents a form of option that the driver + /// takes, for example how many arguments the option has and how + /// they can be provided. Individual option instances store + /// additional information about what group the option is a member + /// of (if any), if the option is an alias, and a number of + /// flags. At runtime the driver parses the command line into + /// concrete Arg instances, each of which corresponds to a + /// particular Option instance. + class Option { + public: + enum OptionClass { + GroupClass = 0, + InputClass, + UnknownClass, + FlagClass, + JoinedClass, + SeparateClass, + CommaJoinedClass, + MultiArgClass, + JoinedOrSeparateClass, + JoinedAndSeparateClass + }; + + private: + OptionClass Kind; + + /// The option ID. + OptSpecifier ID; + + /// The option name. + const char *Name; + + /// Group this option is a member of, if any. + const OptionGroup *Group; + + /// Option that this is an alias for, if any. + const Option *Alias; + + /// Unsupported options will not be rejected. + bool Unsupported : 1; + + /// Treat this option like a linker input? + bool LinkerInput : 1; + + /// When rendering as an input, don't render the option. + + // FIXME: We should ditch the render/renderAsInput distinction. + bool NoOptAsInput : 1; + + /// Always render this option as separate form its value. + bool ForceSeparateRender : 1; + + /// Always render this option joined with its value. + bool ForceJoinedRender : 1; + + /// This option is only consumed by the driver. + bool DriverOption : 1; + + /// This option should not report argument unused errors. + bool NoArgumentUnused : 1; + + protected: + Option(OptionClass Kind, OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); + public: + virtual ~Option(); + + unsigned getID() const { return ID.getID(); } + OptionClass getKind() const { return Kind; } + const char *getName() const { return Name; } + const OptionGroup *getGroup() const { return Group; } + const Option *getAlias() const { return Alias; } + + bool isUnsupported() const { return Unsupported; } + void setUnsupported(bool Value) { Unsupported = Value; } + + bool isLinkerInput() const { return LinkerInput; } + void setLinkerInput(bool Value) { LinkerInput = Value; } + + bool hasNoOptAsInput() const { return NoOptAsInput; } + void setNoOptAsInput(bool Value) { NoOptAsInput = Value; } + + bool hasForceSeparateRender() const { return ForceSeparateRender; } + void setForceSeparateRender(bool Value) { ForceSeparateRender = Value; } + + bool hasForceJoinedRender() const { return ForceJoinedRender; } + void setForceJoinedRender(bool Value) { ForceJoinedRender = Value; } + + bool isDriverOption() const { return DriverOption; } + void setDriverOption(bool Value) { DriverOption = Value; } + + bool hasNoArgumentUnused() const { return NoArgumentUnused; } + void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; } + + bool hasForwardToGCC() const { return !DriverOption && !LinkerInput; } + + /// getUnaliasedOption - Return the final option this option + /// aliases (itself, if the option has no alias). + const Option *getUnaliasedOption() const { + if (Alias) return Alias->getUnaliasedOption(); + return this; + } + + /// getRenderName - Return the name to use when rendering this + /// option. + const char *getRenderName() const { + return getUnaliasedOption()->getName(); + } + + /// matches - Predicate for whether this option is part of the + /// given option (which may be a group). + /// + /// Note that matches against options which are an alias should never be + /// done -- aliases do not participate in matching and so such a query will + /// always be false. + bool matches(OptSpecifier ID) const; + + /// accept - Potentially accept the current argument, returning a + /// new Arg instance, or 0 if the option does not accept this + /// argument (or the argument is missing values). + /// + /// If the option accepts the current argument, accept() sets + /// Index to the position where argument parsing should resume + /// (even if the argument is missing values). + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const = 0; + + void dump() const; + + static bool classof(const Option *) { return true; } + }; + + /// OptionGroup - A set of options which are can be handled uniformly + /// by the driver. + class OptionGroup : public Option { + public: + OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::GroupClass; + } + static bool classof(const OptionGroup *) { return true; } + }; + + // Dummy option classes. + + /// InputOption - Dummy option class for representing driver inputs. + class InputOption : public Option { + public: + InputOption(OptSpecifier ID); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::InputClass; + } + static bool classof(const InputOption *) { return true; } + }; + + /// UnknownOption - Dummy option class for represent unknown arguments. + class UnknownOption : public Option { + public: + UnknownOption(OptSpecifier ID); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::UnknownClass; + } + static bool classof(const UnknownOption *) { return true; } + }; + + // Normal options. + + class FlagOption : public Option { + public: + FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, + const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::FlagClass; + } + static bool classof(const FlagOption *) { return true; } + }; + + class JoinedOption : public Option { + public: + JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, + const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::JoinedClass; + } + static bool classof(const JoinedOption *) { return true; } + }; + + class SeparateOption : public Option { + public: + SeparateOption(OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::SeparateClass; + } + static bool classof(const SeparateOption *) { return true; } + }; + + class CommaJoinedOption : public Option { + public: + CommaJoinedOption(OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::CommaJoinedClass; + } + static bool classof(const CommaJoinedOption *) { return true; } + }; + + // FIXME: Fold MultiArgOption into SeparateOption? + + /// MultiArgOption - An option which takes multiple arguments (these + /// are always separate arguments). + class MultiArgOption : public Option { + unsigned NumArgs; + + public: + MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, + const Option *Alias, unsigned NumArgs); + + unsigned getNumArgs() const { return NumArgs; } + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::MultiArgClass; + } + static bool classof(const MultiArgOption *) { return true; } + }; + + /// JoinedOrSeparateOption - An option which either literally + /// prefixes its (non-empty) value, or is follwed by a value. + class JoinedOrSeparateOption : public Option { + public: + JoinedOrSeparateOption(OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::JoinedOrSeparateClass; + } + static bool classof(const JoinedOrSeparateOption *) { return true; } + }; + + /// JoinedAndSeparateOption - An option which literally prefixes its + /// value and is followed by another value. + class JoinedAndSeparateOption : public Option { + public: + JoinedAndSeparateOption(OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); + + virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + + static bool classof(const Option *O) { + return O->getKind() == Option::JoinedAndSeparateClass; + } + static bool classof(const JoinedAndSeparateOption *) { return true; } + }; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.h b/contrib/llvm/tools/clang/include/clang/Driver/Options.h new file mode 100644 index 0000000..ac312cd --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.h @@ -0,0 +1,32 @@ +//===--- Options.h - Option info & table ------------------------*- 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_OPTIONS_H +#define CLANG_DRIVER_OPTIONS_H + +namespace clang { +namespace driver { + class OptTable; + +namespace options { + enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) OPT_##ID, +#include "clang/Driver/Options.inc" + LastOption +#undef OPTION + }; +} + + OptTable *createDriverOptTable(); +} +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td new file mode 100644 index 0000000..a9a52c0 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td @@ -0,0 +1,715 @@ +//===--- DriverOptions.td - Options for clang -----------------------------===// +// +// 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 options accepted by clang. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +///////// +// Groups + +// Meta-group which defines +def CompileOnly_Group : OptionGroup<"<CompileOnly group>">; + +def I_Group : OptionGroup<"<I 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>; +def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>; +def X_Group : OptionGroup<"<X group>">; +def a_Group : OptionGroup<"<a group>">; +def d_Group : OptionGroup<"<d group>">; +def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>; +def g_Group : OptionGroup<"<g group>">; +def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>; +def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; +def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>; +def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>; +def u_Group : OptionGroup<"<u group>">; + +def pedantic_Group : OptionGroup<"<pedantic group>">, + Group<CompileOnly_Group>; + +// Temporary groups for clang options which we know we don't support, +// but don't want to verbosely warn the user about. +def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">, + Group<f_Group>; +def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, + Group<m_Group>; + +///////// +// Options + +// The internal option ID must be a valid C++ identifier and results in a +// clang::driver::options::OPT_XX enum constant for XX. +// +// We want to unambiguously be able to refer to options from the driver source +// code, for this reason the option name is mangled into an ID. This mangling +// isn't guaranteed to have an inverse, but for practical purposes it does. +// +// The mangling scheme is to ignore the leading '-', and perform the following +// substitutions: +// _ => __ +// - => _ +// # => _HASH +// , => _COMMA +// = => _EQ +// C++ => CXX +// . => _ + +// Developer Driver Options + +def ccc_Group : OptionGroup<"<clang internal options>">; +def ccc_driver_Group : OptionGroup<"<clang driver internal options>">, + Group<ccc_Group>, HelpText<"DRIVER OPTIONS">; +def ccc_debug_Group : OptionGroup<"<clang debug/development internal options>">, + Group<ccc_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">; + +class CCCDriverOpt : Group<ccc_driver_Group>, Flags<[DriverOption, HelpHidden]>; +def ccc_cxx : Flag<"-ccc-cxx">, CCCDriverOpt, + HelpText<"Act as a C++ driver">; +def ccc_echo : Flag<"-ccc-echo">, CCCDriverOpt, + HelpText<"Echo commands before running them">; +def ccc_gcc_name : Separate<"-ccc-gcc-name">, CCCDriverOpt, + HelpText<"Name for native GCC compiler">, + MetaVarName<"<gcc-path>">; +def ccc_clang_cxx : Flag<"-ccc-clang-cxx">, CCCDriverOpt, + HelpText<"Enable the clang compiler for C++">; +def ccc_no_clang_cxx : Flag<"-ccc-no-clang-cxx">, CCCDriverOpt, + HelpText<"Disable the clang compiler for C++">; +def ccc_no_clang : Flag<"-ccc-no-clang">, CCCDriverOpt, + HelpText<"Disable the clang compiler">; +def ccc_no_clang_cpp : Flag<"-ccc-no-clang-cpp">, CCCDriverOpt, + HelpText<"Disable the clang preprocessor">; +def ccc_clang_archs : Separate<"-ccc-clang-archs">, CCCDriverOpt, + HelpText<"Comma separate list of architectures to use the clang compiler for">, + MetaVarName<"<arch-list>">; +def ccc_pch_is_pch : Flag<"-ccc-pch-is-pch">, CCCDriverOpt, + HelpText<"Use lazy PCH for precompiled headers">; +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, + HelpText<"Dump parsed command line arguments">; +def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt, + HelpText<"Dump list of actions to perform">; +def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt, + HelpText<"Show bindings of tools to actions">; + +// Make sure all other -ccc- options are rejected. +def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>; + +// Standard Options + +def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, + HelpText<"Print the commands to run for this compilation">; +def A : JoinedOrSeparate<"-A">; +def B : JoinedOrSeparate<"-B">; +def CC : Flag<"-CC">; +def C : Flag<"-C">; +def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; +def E : Flag<"-E">, Flags<[DriverOption]>, + HelpText<"Only run the preprocessor">; +def F : JoinedOrSeparate<"-F">; +def H : Flag<"-H">; +def I_ : Flag<"-I-">, Group<I_Group>; +def I : JoinedOrSeparate<"-I">, Group<I_Group>; +def L : JoinedOrSeparate<"-L">; +def MD : Flag<"-MD">, Group<M_Group>; +def MF : JoinedOrSeparate<"-MF">, Group<M_Group>; +def MG : Flag<"-MG">, Group<M_Group>; +def MMD : Flag<"-MMD">, Group<M_Group>; +def MM : Flag<"-MM">, Group<M_Group>; +def MP : Flag<"-MP">, Group<M_Group>; +def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>; +def MT : JoinedOrSeparate<"-MT">, Group<M_Group>; +def Mach : Flag<"-Mach">; +def M : Flag<"-M">, Group<M_Group>; +def O0 : Joined<"-O0">, Group<O_Group>; +def O4 : Joined<"-O4">, Group<O_Group>; +def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>, + HelpText<"Treat source input files as Objective-C++ inputs">; +def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>, + HelpText<"Treat source input files as Objective-C inputs">; +def O : Joined<"-O">, Group<O_Group>; +def P : Flag<"-P">; +def Qn : Flag<"-Qn">; +def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>, + HelpText<"Don't emit warning for unused driver arguments">; +def Q : Flag<"-Q">; +def R : Flag<"-R">; +def S : Flag<"-S">, Flags<[DriverOption]>, + HelpText<"Only run preprocess and compilation steps">; +def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>; +def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>; +def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>; +def T : JoinedOrSeparate<"-T">, Group<T_Group>; +def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>; +def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>; +def Wa_COMMA : CommaJoined<"-Wa,">, + HelpText<"Pass the comma separated arguments in <arg> to the assembler">, + MetaVarName<"<arg>">; +def Wall : Flag<"-Wall">, Group<W_Group>; +def Wextra : Flag<"-Wextra">, Group<W_Group>; +def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, + HelpText<"Pass the comma separated arguments in <arg> to the linker">, + MetaVarName<"<arg>">; +def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>; +def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>; +def Wp_COMMA : CommaJoined<"-Wp,">, + HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">, + MetaVarName<"<arg>">; +def W_Joined : Joined<"-W">, Group<W_Group>; +def Xanalyzer : Separate<"-Xanalyzer">, + HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">; +def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>; +def Xassembler : Separate<"-Xassembler">, + HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">; +def Xclang : Separate<"-Xclang">, + HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">; +def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>, + HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">; +def Xpreprocessor : Separate<"-Xpreprocessor">, + HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">; +def X_Flag : Flag<"-X">; +def X_Joined : Joined<"-X">; +def Z_Flag : Flag<"-Z">; +def Z_Joined : Joined<"-Z">; +def all__load : Flag<"-all_load">; +def allowable__client : Separate<"-allowable_client">; +def ansi : Flag<"-ansi">, Group<a_Group>; +def arch__errors__fatal : Flag<"-arch_errors_fatal">; +def arch : Separate<"-arch">, Flags<[DriverOption]>; +def a : Joined<"-a">, Group<a_Group>; +def bind__at__load : Flag<"-bind_at_load">; +def bundle__loader : Separate<"-bundle_loader">; +def bundle : Flag<"-bundle">; +def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>; +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 current__version : JoinedOrSeparate<"-current_version">; +def c : Flag<"-c">, Flags<[DriverOption]>, + HelpText<"Only run preprocess, compile, and assemble steps">; +def dA : Flag<"-dA">, Group<d_Group>; +def dD : Flag<"-dD">, Group<d_Group>; +def dM : Flag<"-dM">, Group<d_Group>; +def dead__strip : Flag<"-dead_strip">; +def dependency_file : Separate<"-dependency-file">; +def dumpmachine : Flag<"-dumpmachine">, Flags<[Unsupported]>; +def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>; +def dumpversion : Flag<"-dumpversion">; +def dylib__file : Separate<"-dylib_file">; +def dylinker__install__name : JoinedOrSeparate<"-dylinker_install_name">; +def dylinker : Flag<"-dylinker">; +def dynamiclib : Flag<"-dynamiclib">; +def dynamic : Flag<"-dynamic">, Flags<[NoArgumentUnused]>; +def d_Flag : Flag<"-d">, Group<d_Group>; +def d_Joined : Joined<"-d">, Group<d_Group>; +def emit_ast : Flag<"-emit-ast">, + HelpText<"Emit Clang AST files for source inputs">; +def emit_llvm : Flag<"-emit-llvm">, + HelpText<"Use the LLVM representation for assembler and object files">; +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>; +def faccess_control : Flag<"-faccess-control">, Group<f_Group>; +def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; +def fasm : Flag<"-fasm">, Group<f_Group>; +def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>; +def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>; +def fastcp : Flag<"-fastcp">, Group<f_Group>; +def fastf : Flag<"-fastf">, Group<f_Group>; +def fast : Flag<"-fast">, Group<f_Group>; +def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>; +def fblocks : Flag<"-fblocks">, Group<f_Group>; +def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; +def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; +def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; +def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; +def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, + Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">; +def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; +def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>; +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 fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; +def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; +def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; +def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>; +def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; +def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; +def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>; +def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, 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>; +def fencoding_EQ : Joined<"-fencoding=">, 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 ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; +def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>; +def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; +def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; +def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; +def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Group<f_Group>; +def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>; +def finline : Flag<"-finline">, Group<clang_ignored_f_Group>; +def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>; +def flat__namespace : Flag<"-flat_namespace">; +def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>; +def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>; +def flto : Flag<"-flto">, 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>; +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_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>; +def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; +def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>; +def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>; +def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>; +def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>; +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_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>; +def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>; +def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, 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_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_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_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; +def fno_ms_extensions : Flag<"-fno-ms-extensions">, 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_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; +def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; +def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>; +def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>; +def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; +def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<clang_ignored_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>; +def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; +def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; +def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>; +def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; +def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; +def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, 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_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; +def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>; +def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>; +def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>; +def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, Group<f_Group>; +def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group<f_Group>; +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 force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">; +def force__flat__namespace : Flag<"-force_flat_namespace">; +def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, 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>; +def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>; +def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>; +def framework : Separate<"-framework">, Flags<[LinkerInput]>; +def frtti : Flag<"-frtti">, Group<f_Group>; +def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>; +def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>; +def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>; +def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>; +def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>; +def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>; +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<clang_ignored_f_Group>; +def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; +def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; +def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; +def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; +def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, + Group<f_Group>; +def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; +def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; +def ftime_report : Flag<"-ftime-report">, Group<f_Group>; +def ftrapv : Flag<"-ftrapv">, Group<f_Group>; +def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; +def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; +def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>; +def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; +def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>; +def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; +def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; +def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; +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 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 idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>; +def iframework : JoinedOrSeparate<"-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">; +def init : Separate<"-init">; +def install__name : Separate<"-install_name">; +def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>; +def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>; +def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>; +def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>; +def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>; +def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>; +def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>; +def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<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 m32 : Flag<"-m32">, 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]>; +def mabi_EQ : Joined<"-mabi=">, Group<m_Group>, Flags<[DriverOption]>; +def march_EQ : Joined<"-march=">, Group<m_Group>, Flags<[DriverOption]>; +def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>, Flags<[DriverOption]>; +def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>; +def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>; +def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>; +def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>; +def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; +def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>; +def mhard_float : Flag<"-mhard-float">, Group<m_Group>; +def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>, Flags<[DriverOption]>; +def mkernel : Flag<"-mkernel">, Group<m_Group>; +def mllvm : Separate<"-mllvm">; +def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>, Flags<[DriverOption]>; +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>; +def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>; +def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>; +def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>; +def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; +def mno_relax_all : Flag<"-mno-relax-all">, Group<m_Group>; +def mno_soft_float : Flag<"-mno-soft-float">, 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>; +def mno_sse4 : Flag<"-mno-sse4">, Group<m_x86_Features_Group>; +def mno_sse4_1 : Flag<"-mno-sse4.1">, Group<m_x86_Features_Group>; +def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>; +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_thumb : Flag<"-mno-thumb">, Group<m_Group>; +def marm : Flag<"-marm">, Alias<mno_thumb>; + +def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; +def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; +def mred_zone : Flag<"-mred-zone">, Group<m_Group>; +def mrelax_all : Flag<"-mrelax-all">, 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>; +def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>; +def msse4 : Flag<"-msse4">, Group<m_x86_Features_Group>; +def msse4_1 : Flag<"-msse4.1">, Group<m_x86_Features_Group>; +def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>; +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 mthumb : Flag<"-mthumb">, Group<m_Group>; +def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; +def multi__module : Flag<"-multi_module">; +def multiply__defined__unused : Separate<"-multiply_defined_unused">; +def multiply__defined : Separate<"-multiply_defined">; +def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>; +def m_Separate : Separate<"-m">, Group<m_Group>; +def m_Joined : Joined<"-m">, Group<m_Group>; +def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>, + HelpText<"Use relative instead of canonical paths">; +def no_cpp_precomp : Flag<"-no-cpp-precomp">; +def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; +def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; +def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; +def nobuiltininc : Flag<"-nobuiltininc">; +def nodefaultlibs : Flag<"-nodefaultlibs">; +def nofixprebinding : Flag<"-nofixprebinding">; +def nolibc : Flag<"-nolibc">; +def nomultidefs : Flag<"-nomultidefs">; +def noprebind : Flag<"-noprebind">; +def noseglinkedit : Flag<"-noseglinkedit">; +def nostartfiles : Flag<"-nostartfiles">; +def nostdinc : Flag<"-nostdinc">; +def nostdincxx : Flag<"-nostdinc++">; +def nostdlib : Flag<"-nostdlib">; +def object : Flag<"-object">; +def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>, + HelpText<"Write output to <file>">, MetaVarName<"<file>">; +def pagezero__size : JoinedOrSeparate<"-pagezero_size">; +def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>; +def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>; +def pedantic : Flag<"-pedantic">, Group<pedantic_Group>; +def pg : Flag<"-pg">; +def pipe : Flag<"-pipe">, + HelpText<"Use pipes between commands, when possible">; +def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">; +def prebind : Flag<"-prebind">; +def preload : Flag<"-preload">; +def print_file_name_EQ : Joined<"-print-file-name=">, + HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">; +def print_ivar_layout : Flag<"-print-ivar-layout">; +def print_libgcc_file_name : Flag<"-print-libgcc-file-name">, + HelpText<"Print the library path for \"libgcc.a\"">; +def print_multi_directory : Flag<"-print-multi-directory">; +def print_multi_lib : Flag<"-print-multi-lib">; +def print_multi_os_directory : Flag<"-print-multi-os-directory">; +def print_prog_name_EQ : Joined<"-print-prog-name=">, + HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">; +def print_search_dirs : Flag<"-print-search-dirs">, + HelpText<"Print the paths used for finding libraries and programs">; +def private__bundle : Flag<"-private_bundle">; +def pthreads : Flag<"-pthreads">; +def pthread : Flag<"-pthread">; +def p : Flag<"-p">; +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 rpath : Separate<"-rpath">, Flags<[LinkerInput]>; +def r : Flag<"-r">; +def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>, + HelpText<"Save intermediate compilation results">; +def sectalign : MultiArg<"-sectalign", 3>; +def sectcreate : MultiArg<"-sectcreate", 3>; +def sectobjectsymbols : MultiArg<"-sectobjectsymbols", 2>; +def sectorder : MultiArg<"-sectorder", 3>; +def seg1addr : JoinedOrSeparate<"-seg1addr">; +def seg__addr__table__filename : Separate<"-seg_addr_table_filename">; +def seg__addr__table : Separate<"-seg_addr_table">; +def segaddr : MultiArg<"-segaddr", 2>; +def segcreate : MultiArg<"-segcreate", 3>; +def seglinkedit : Flag<"-seglinkedit">; +def segprot : MultiArg<"-segprot", 3>; +def segs__read__only__addr : Separate<"-segs_read_only_addr">; +def segs__read__write__addr : Separate<"-segs_read_write_addr">; +def segs__read__ : Joined<"-segs_read_">; +def shared_libgcc : Flag<"-shared-libgcc">; +def shared : Flag<"-shared">; +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 : Flag<"-static">, Flags<[NoArgumentUnused]>; +def std_default_EQ : Joined<"-std-default=">; +def std_EQ : Joined<"-std=">; +def sub__library : JoinedOrSeparate<"-sub_library">; +def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">; +def s : Flag<"-s">; +def time : Flag<"-time">, + HelpText<"Time individual commands">; +def traditional_cpp : Flag<"-traditional-cpp">; +def traditional : Flag<"-traditional">; +def trigraphs : Flag<"-trigraphs">; +def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">; +def twolevel__namespace : Flag<"-twolevel_namespace">; +def t : Flag<"-t">; +def umbrella : Separate<"-umbrella">; +def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>; +def undef : Flag<"-undef">, Group<u_Group>; +def unexported__symbols__list : Separate<"-unexported_symbols_list">; +def u : JoinedOrSeparate<"-u">, Group<u_Group>; +def v : Flag<"-v">, + HelpText<"Show commands to run and use verbose output">; +def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>; +def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>; +def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>; +def weak__reference__mismatches : Separate<"-weak_reference_mismatches">; +def whatsloaded : Flag<"-whatsloaded">; +def whyload : Flag<"-whyload">; +def w : Flag<"-w">; +def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>, + HelpText<"Treat subsequent input files as having type <language>">, + MetaVarName<"<language>">; +def y : Joined<"-y">; + +// Double dash options, which are usually an alias for one of the previous +// options. + +def _CLASSPATH_EQ : Joined<"--CLASSPATH=">, Alias<fclasspath_EQ>; +def _CLASSPATH : Separate<"--CLASSPATH">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; +def _all_warnings : Flag<"--all-warnings">, Alias<Wall>; +def _analyze_auto : Flag<"--analyze-auto">, Flags<[DriverOption]>; +def _analyzer_no_default_checks : Flag<"--analyzer-no-default-checks">, Flags<[DriverOption]>; +def _analyzer_output : JoinedOrSeparate<"--analyzer-output">, Flags<[DriverOption]>; +def _analyze : Flag<"--analyze">, Flags<[DriverOption]>, + HelpText<"Run the static analyzer">; +def _ansi : Flag<"--ansi">, Alias<ansi>; +def _assemble : Flag<"--assemble">, Alias<S>; +def _assert_EQ : Joined<"--assert=">, Alias<A>, Flags<[RenderSeparate]>; +def _assert : Separate<"--assert">, Alias<A>; +def _bootclasspath_EQ : Joined<"--bootclasspath=">, Alias<fbootclasspath_EQ>; +def _bootclasspath : Separate<"--bootclasspath">, Alias<fbootclasspath_EQ>, Flags<[RenderJoined]>; +def _classpath_EQ : Joined<"--classpath=">, Alias<fclasspath_EQ>; +def _classpath : Separate<"--classpath">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; +def _combine : Flag<"--combine">, Alias<combine>, Flags<[Unsupported]>; +def _comments_in_macros : Flag<"--comments-in-macros">, Alias<CC>; +def _comments : Flag<"--comments">, Alias<C>; +def _compile : Flag<"--compile">, Alias<c>; +def _constant_cfstrings : Flag<"--constant-cfstrings">; +def _coverage : Flag<"--coverage">, Alias<coverage>; +def _debug_EQ : Joined<"--debug=">, Alias<g_Flag>, Flags<[Unsupported]>; +def _debug : Flag<"--debug">, Alias<g_Flag>, Flags<[Unsupported]>; +def _define_macro_EQ : Joined<"--define-macro=">, Alias<D>; +def _define_macro : Separate<"--define-macro">, Alias<D>, Flags<[RenderJoined]>; +def _dependencies : Flag<"--dependencies">, Alias<M>; +def _encoding_EQ : Joined<"--encoding=">, Alias<fencoding_EQ>; +def _encoding : Separate<"--encoding">, Alias<fencoding_EQ>, Flags<[RenderJoined]>; +def _entry : Flag<"--entry">, Alias<e>; +def _extdirs_EQ : Joined<"--extdirs=">, Alias<fextdirs_EQ>; +def _extdirs : Separate<"--extdirs">, Alias<fextdirs_EQ>, Flags<[RenderJoined]>; +def _extra_warnings : Flag<"--extra-warnings">, Alias<W_Joined>; +def _for_linker_EQ : Joined<"--for-linker=">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput, RenderSeparate]>; +def _for_linker : Separate<"--for-linker">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput]>; +def _force_link_EQ : Joined<"--force-link=">, Alias<u>, Flags<[RenderSeparate]>; +def _force_link : Separate<"--force-link">, Alias<u>; +def _help_hidden : Flag<"--help-hidden">; +def _help : Flag<"--help">, + HelpText<"Display available options">; +def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>, Flags<[RenderSeparate]>; +def _imacros : Separate<"--imacros">, Alias<imacros>; +def _include_barrier : Flag<"--include-barrier">, Alias<I_>; +def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias<idirafter>, Flags<[RenderSeparate]>; +def _include_directory_after : Separate<"--include-directory-after">, Alias<idirafter>; +def _include_directory_EQ : Joined<"--include-directory=">, Alias<I>; +def _include_directory : Separate<"--include-directory">, Alias<I>, Flags<[RenderJoined]>; +def _include_prefix_EQ : Joined<"--include-prefix=">, Alias<iprefix>, Flags<[RenderSeparate]>; +def _include_prefix : Separate<"--include-prefix">, Alias<iprefix>; +def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix_after : Separate<"--include-with-prefix-after">, Alias<iwithprefix>; +def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias<iwithprefixbefore>, Flags<[RenderSeparate]>; +def _include_with_prefix_before : Separate<"--include-with-prefix-before">, Alias<iwithprefixbefore>; +def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix : Separate<"--include-with-prefix">, Alias<iwithprefix>; +def _include_EQ : Joined<"--include=">, Alias<include_>, Flags<[RenderSeparate]>; +def _include : Separate<"--include">, Alias<include_>; +def _language_EQ : Joined<"--language=">, Alias<x>, Flags<[RenderSeparate]>; +def _language : Separate<"--language">, Alias<x>; +def _library_directory_EQ : Joined<"--library-directory=">, Alias<L>, Flags<[RenderSeparate]>; +def _library_directory : Separate<"--library-directory">, Alias<L>; +def _machine__EQ : Joined<"--machine-=">, Alias<m_Joined>, Flags<[Unsupported]>; +def _machine_ : Joined<"--machine-">, Alias<m_Joined>, Flags<[Unsupported]>; +def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>; +def _machine : Separate<"--machine">, Alias<m_Joined>, Flags<[RenderJoined]>; +def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>; +def _no_line_commands : Flag<"--no-line-commands">, Alias<P>; +def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>; +def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>; +def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>; +def _no_warnings : Flag<"--no-warnings">, Alias<w>; +def _optimize_EQ : Joined<"--optimize=">, Alias<O>, Flags<[Unsupported]>; +def _optimize : Flag<"--optimize">, Alias<O>, Flags<[Unsupported]>; +def _output_class_directory_EQ : Joined<"--output-class-directory=">, Alias<foutput_class_dir_EQ>; +def _output_class_directory : Separate<"--output-class-directory">, Alias<foutput_class_dir_EQ>, Flags<[RenderJoined]>; +def _output_EQ : Joined<"--output=">, Alias<o>, Flags<[RenderSeparate]>; +def _output : Separate<"--output">, Alias<o>; +def _param : Separate<"--param">; +def _param_EQ : Joined<"--param=">, Alias<_param>, Flags<[RenderSeparate]>; +def _pass_exit_codes : Flag<"--pass-exit-codes">, Alias<pass_exit_codes>; +def _pedantic_errors : Flag<"--pedantic-errors">, Alias<pedantic_errors>; +def _pedantic : Flag<"--pedantic">, Alias<pedantic>; +def _pipe : Flag<"--pipe">, Alias<pipe>, Flags<[DriverOption]>; +def _prefix_EQ : Joined<"--prefix=">, Alias<B>, Flags<[RenderSeparate]>; +def _prefix : Separate<"--prefix">, Alias<B>; +def _preprocess : Flag<"--preprocess">, Alias<E>; +def _print_diagnostic_categories : Flag<"--print-diagnostic-categories">; +def _print_file_name_EQ : Joined<"--print-file-name=">, Alias<print_file_name_EQ>; +def _print_file_name : Separate<"--print-file-name">, Alias<print_file_name_EQ>; +def _print_libgcc_file_name : Flag<"--print-libgcc-file-name">, Alias<print_libgcc_file_name>; +def _print_missing_file_dependencies : Flag<"--print-missing-file-dependencies">, Alias<MG>; +def _print_multi_directory : Flag<"--print-multi-directory">, Alias<print_multi_directory>; +def _print_multi_lib : Flag<"--print-multi-lib">, Alias<print_multi_lib>; +def _print_multi_os_directory : Flag<"--print-multi-os-directory">, Alias<print_multi_os_directory>; +def _print_prog_name_EQ : Joined<"--print-prog-name=">, Alias<print_prog_name_EQ>; +def _print_prog_name : Separate<"--print-prog-name">, Alias<print_prog_name_EQ>; +def _print_search_dirs : Flag<"--print-search-dirs">, Alias<print_search_dirs>; +def _profile_blocks : Flag<"--profile-blocks">, Alias<a>; +def _profile : Flag<"--profile">, Alias<p>; +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>, Flags<[RenderJoined]>; +def _save_temps : Flag<"--save-temps">, Alias<save_temps>; +def _shared : Flag<"--shared">, Alias<shared>; +def _signed_char : Flag<"--signed-char">, Alias<fsigned_char>; +def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>, Flags<[Unsupported]>; +def _specs : Separate<"--specs">, Alias<specs_EQ>, Flags<[RenderJoined, Unsupported]>; +def _static : Flag<"--static">, Alias<static>; +def _std_EQ : Joined<"--std=">, Alias<std_EQ>; +def _std : Separate<"--std">, Alias<std_EQ>, Flags<[RenderJoined]>; +def _sysroot_EQ : Joined<"--sysroot=">; +def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>, Flags<[RenderJoined]>; +def _target_help : Flag<"--target-help">; +def _trace_includes : Flag<"--trace-includes">, Alias<H>; +def _traditional_cpp : Flag<"--traditional-cpp">, Alias<traditional_cpp>; +def _traditional : Flag<"--traditional">, Alias<traditional>; +def _trigraphs : Flag<"--trigraphs">, Alias<trigraphs>; +def _undefine_macro_EQ : Joined<"--undefine-macro=">, Alias<U>; +def _undefine_macro : Separate<"--undefine-macro">, Alias<U>, Flags<[RenderJoined]>; +def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>; +def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>; +def _verbose : Flag<"--verbose">, Alias<v>; +def _version : Flag<"--version">; +def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>, Flags<[Unsupported]>; +def _warn_ : Joined<"--warn-">, Alias<W_Joined>, Flags<[Unsupported]>; +def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>; +def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>; +def _ : Joined<"--">, Alias<f>, Flags<[Unsupported]>; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Phases.h b/contrib/llvm/tools/clang/include/clang/Driver/Phases.h new file mode 100644 index 0000000..a0c42ea --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Phases.h @@ -0,0 +1,32 @@ +//===--- Phases.h - Transformations on Driver Types -------------*- 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_PHASES_H_ +#define CLANG_DRIVER_PHASES_H_ + +namespace clang { +namespace driver { +namespace phases { + /// ID - Ordered values for successive stages in the + /// compilation process which interact with user options. + enum ID { + Preprocess, + Precompile, + Compile, + Assemble, + Link + }; + + const char *getPhaseName(ID Id); + +} // end namespace phases +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h new file mode 100644 index 0000000..4368a81 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h @@ -0,0 +1,80 @@ +//===--- Tool.h - Compilation Tools -----------------------------*- 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_TOOL_H_ +#define CLANG_DRIVER_TOOL_H_ + +namespace llvm { + template<typename T, unsigned N> class SmallVector; +} + +namespace clang { +namespace driver { + class ArgList; + class Compilation; + class InputInfo; + class Job; + class JobAction; + class ToolChain; + + typedef llvm::SmallVector<InputInfo, 4> InputInfoList; + +/// Tool - Information on a specific compilation tool. +class Tool { + /// The tool name (for debugging). + const char *Name; + + /// The human readable name for the tool, for use in diagnostics. + const char *ShortName; + + /// The tool chain this tool is a part of. + const ToolChain &TheToolChain; + +public: + Tool(const char *Name, const char *ShortName, + const ToolChain &TC); + +public: + virtual ~Tool(); + + const char *getName() const { return Name; } + + const char *getShortName() const { return ShortName; } + + const ToolChain &getToolChain() const { return TheToolChain; } + + virtual bool acceptsPipedInput() const = 0; + virtual bool canPipeOutput() const = 0; + virtual bool hasIntegratedAssembler() const { return false; } + virtual bool hasIntegratedCPP() const = 0; + + /// \brief Does this tool have "good" standardized diagnostics, or should the + /// driver add an additional "command failed" diagnostic on failures. + virtual bool hasGoodDiagnostics() const { return false; } + + /// ConstructJob - Construct jobs to perform the action \arg JA, + /// writing to \arg Output and with \arg Inputs. + /// + /// \param Dest - Where to put the resulting commands. + /// \param TCArgs - The argument list for this toolchain, with any + /// tool chain specific translations applied. + /// \param LinkingOutput - If this output will eventually feed the + /// linker, then this is the final output name of the linked image. + virtual void ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const = 0; +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h new file mode 100644 index 0000000..1a8ae77 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h @@ -0,0 +1,141 @@ +//===--- ToolChain.h - Collections of tools for one platform ----*- 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_TOOLCHAIN_H_ +#define CLANG_DRIVER_TOOLCHAIN_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/System/Path.h" +#include <string> + +namespace clang { +namespace driver { + class Compilation; + class DerivedArgList; + class Driver; + class HostInfo; + class InputArgList; + class JobAction; + class Tool; + +/// ToolChain - Access to tools for a single platform. +class ToolChain { +public: + typedef llvm::SmallVector<std::string, 4> path_list; + +private: + const HostInfo &Host; + const llvm::Triple Triple; + + /// The list of toolchain specific path prefixes to search for + /// files. + path_list FilePaths; + + /// The list of toolchain specific path prefixes to search for + /// programs. + path_list ProgramPaths; + +protected: + ToolChain(const HostInfo &Host, const llvm::Triple &_Triple); + +public: + virtual ~ToolChain(); + + // Accessors + + const Driver &getDriver() const; + const llvm::Triple &getTriple() const { return Triple; } + + llvm::StringRef getArchName() const { return Triple.getArchName(); } + llvm::StringRef getPlatform() const { return Triple.getVendorName(); } + llvm::StringRef getOS() const { return Triple.getOSName(); } + + std::string getTripleString() const { + return Triple.getTriple(); + } + + path_list &getFilePaths() { return FilePaths; } + const path_list &getFilePaths() const { return FilePaths; } + + path_list &getProgramPaths() { return ProgramPaths; } + const path_list &getProgramPaths() const { return ProgramPaths; } + + // Tool access. + + /// TranslateArgs - Create a new derived argument list for any argument + /// translations this ToolChain may wish to perform. + /// + /// \param BoundArch - The bound architecture name, or 0. + virtual DerivedArgList *TranslateArgs(InputArgList &Args, + const char *BoundArch) const = 0; + + /// SelectTool - Choose a tool to use to handle the action \arg JA. + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const = 0; + + // Helper methods + + std::string GetFilePath(const Compilation &C, const char *Name) const; + std::string GetProgramPath(const Compilation &C, const char *Name, + bool WantFile = false) const; + + // Platform defaults information + + /// IsBlocksDefault - Does this tool chain enable -fblocks by default. + virtual bool IsBlocksDefault() const { return false; } + + /// IsIntegratedAssemblerDefault - Does this tool chain enable -integrated-as + /// by default. + virtual bool IsIntegratedAssemblerDefault() const { return false; } + + /// IsObjCNonFragileABIDefault - Does this tool chain set + /// -fobjc-nonfragile-abi by default. + virtual bool IsObjCNonFragileABIDefault() const { return false; } + + /// 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; } + + /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the + /// mixed dispatch method be used? + virtual bool UseObjCMixedDispatch() const { return false; } + + /// GetDefaultStackProtectorLevel - Get the default stack protector level for + /// this tool chain (0=off, 1=on, 2=all). + virtual unsigned GetDefaultStackProtectorLevel() const { return 0; } + + /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables + /// by default. + virtual bool IsUnwindTablesDefault() const = 0; + + /// GetDefaultRelocationModel - Return the LLVM name of the default + /// relocation model for this tool chain. + virtual const char *GetDefaultRelocationModel() const = 0; + + /// GetForcedPicModel - Return the LLVM name of the forced PIC model + /// for this tool chain, or 0 if this tool chain does not force a + /// particular PIC mode. + virtual const char *GetForcedPicModel() const = 0; + + /// Does this tool chain support Objective-C garbage collection. + virtual bool SupportsObjCGC() const { return false; } + + /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf + /// compile unit information. + virtual bool UseDwarfDebugFlags() const { return false; } + + /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. + virtual bool UseSjLjExceptions() const { return false; } +}; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.def b/contrib/llvm/tools/clang/include/clang/Driver/Types.def new file mode 100644 index 0000000..61a5043 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def @@ -0,0 +1,81 @@ +//===--- Types.def - Driver Type info ---------------------------*- 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 driver type information. Users of this file +// must define the TYPE macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +#ifndef TYPE +#error "Define TYPE prior to including this file!" +#endif + +// TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) + +// The first value is the type name as a string; for types which can +// be user specified this should be the equivalent -x option. + +// The second value is the type id, which will result in a +// clang::driver::types::TY_XX enum constant. + +// The third value is that id of the type for preprocessed inputs of +// this type, or INVALID if this type is not preprocessed. + +// The fourth value is the suffix to use when creating temporary files +// of this type, or null if unspecified. + +// The fifth value is a string containt option flags. Valid values: +// a - The type should only be assembled. +// p - The type should only be precompiled. +// u - The type can be user specified (with -x). +// A - The type's temporary suffix should be appended when generating +// outputs of this type. + + +// C family source language (with and without preprocessing). +TYPE("cpp-output", PP_C, INVALID, "i", "u") +TYPE("c", C, PP_C, 0, "u") +TYPE("cl", CL, PP_C, 0, "u") +TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u") +TYPE("objective-c", ObjC, PP_ObjC, 0, "u") +TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u") +TYPE("c++", CXX, PP_CXX, 0, "u") +TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u") +TYPE("objective-c++", ObjCXX, PP_ObjCXX, 0, "u") + +// C family input files to precompile. +TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p") +TYPE("c-header", CHeader, PP_CHeader, 0, "pu") +TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p") +TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, 0, "pu") +TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p") +TYPE("c++-header", CXXHeader, PP_CXXHeader, 0, "pu") +TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p") +TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu") + +// Other languages. +TYPE("ada", Ada, INVALID, 0, "u") +TYPE("assembler", PP_Asm, INVALID, "s", "au") +TYPE("assembler-with-cpp", Asm, PP_Asm, 0, "au") +TYPE("f95", PP_Fortran, INVALID, 0, "u") +TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u") +TYPE("java", Java, INVALID, 0, "u") + +// Misc. +TYPE("ast", AST, INVALID, "ast", "u") +TYPE("llvm-asm", LLVMAsm, INVALID, "s", "") +TYPE("llvm-bc", LLVMBC, INVALID, "o", "") +TYPE("plist", Plist, INVALID, "plist", "") +TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "") +TYPE("precompiled-header", PCH, INVALID, "gch", "A") +TYPE("object", Object, INVALID, "o", "") +TYPE("treelang", Treelang, INVALID, 0, "u") +TYPE("image", Image, INVALID, "out", "") +TYPE("dependencies", Dependencies, INVALID, "d", "") +TYPE("none", Nothing, INVALID, 0, "u") diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.h b/contrib/llvm/tools/clang/include/clang/Driver/Types.h new file mode 100644 index 0000000..d933230 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.h @@ -0,0 +1,92 @@ +//===--- Types.h - Input & Temporary Driver Types ---------------*- 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_TYPES_H_ +#define CLANG_DRIVER_TYPES_H_ + +#include "clang/Driver/Phases.h" + +namespace clang { +namespace driver { +namespace types { + enum ID { + TY_INVALID, +#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) TY_##ID, +#include "clang/Driver/Types.def" +#undef TYPE + TY_LAST + }; + + /// getTypeName - Return the name of the type for \arg Id. + const char *getTypeName(ID Id); + + /// getPreprocessedType - Get the ID of the type for this input when + /// it has been preprocessed, or INVALID if this input is not + /// preprocessed. + ID getPreprocessedType(ID Id); + + /// getTypeTempSuffix - Return the suffix to use when creating a + /// temp file of this type, or null if unspecified. + const char *getTypeTempSuffix(ID Id); + + /// onlyAssembleType - Should this type only be assembled. + bool onlyAssembleType(ID Id); + + /// onlyPrecompileType - Should this type only be precompiled. + bool onlyPrecompileType(ID Id); + + /// canTypeBeUserSpecified - Can this type be specified on the + /// command line (by the type name); this is used when forwarding + /// commands to gcc. + bool canTypeBeUserSpecified(ID Id); + + /// appendSuffixForType - When generating outputs of this type, + /// should the suffix be appended (instead of replacing the existing + /// suffix). + bool appendSuffixForType(ID Id); + + /// canLipoType - Is this type acceptable as the output of a + /// universal build (currently, just the Nothing, Image, and Object + /// types). + bool canLipoType(ID Id); + + /// isAcceptedByClang - Can clang handle this input type. + bool isAcceptedByClang(ID Id); + + /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers). + bool isCXX(ID Id); + + /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers). + bool isObjC(ID Id); + + /// lookupTypeForExtension - Lookup the type to use for the file + /// extension \arg Ext. + ID lookupTypeForExtension(const char *Ext); + + /// lookupTypeForTypSpecifier - Lookup the type to use for a user + /// specified type name. + ID lookupTypeForTypeSpecifier(const char *Name); + + /// getNumCompilationPhases - Return the complete number of phases + /// to be done for this type. + unsigned getNumCompilationPhases(ID Id); + + /// getCompilationPhase - Return the \args N th compilation phase to + /// be done for this type. + phases::ID getCompilationPhase(ID Id, unsigned N); + + /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given + /// C type (used for clang++ emulation of g++ behaviour) + ID lookupCXXTypeForCType(ID Id); + +} // end namespace types +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Util.h b/contrib/llvm/tools/clang/include/clang/Driver/Util.h new file mode 100644 index 0000000..52f268d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Driver/Util.h @@ -0,0 +1,30 @@ +//===--- Util.h - Common Driver Utilities -----------------------*- 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_UTIL_H_ +#define CLANG_DRIVER_UTIL_H_ + +namespace llvm { + template<typename T, unsigned N> class SmallVector; +} + +namespace clang { +namespace driver { + class Action; + + /// ArgStringList - Type used for constructing argv lists for subprocesses. + typedef llvm::SmallVector<const char*, 16> ArgStringList; + + /// ActionList - Type used for lists of actions. + typedef llvm::SmallVector<Action*, 3> ActionList; + +} // end namespace driver +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h new file mode 100644 index 0000000..9163a20 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h @@ -0,0 +1,87 @@ +//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AST Consumers. +// +//===----------------------------------------------------------------------===// + +#ifndef DRIVER_ASTCONSUMERS_H +#define DRIVER_ASTCONSUMERS_H + +#include <string> + +namespace llvm { + class raw_ostream; + class Module; + class LLVMContext; + namespace sys { class Path; } +} +namespace clang { + +class ASTConsumer; +class CodeGenOptions; +class Diagnostic; +class FileManager; +class LangOptions; +class Preprocessor; +class TargetOptions; + +// AST pretty-printer: prints out the AST in a format that is close to the +// original C code. The output is intended to be in a format such that +// clang could re-parse the output back into the same AST, but the +// implementation is still incomplete. +ASTConsumer *CreateASTPrinter(llvm::raw_ostream *OS); + +// AST XML-printer: prints out the AST in a XML format +// The output is intended to be in a format such that +// clang or any other tool could re-parse the output back into the same AST, +// but the implementation is still incomplete. +ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream *OS); + +// AST dumper: dumps the raw AST in human-readable form to stderr; this is +// intended for debugging. +ASTConsumer *CreateASTDumper(); + +// Graphical AST viewer: for each function definition, creates a graph of +// the AST and displays it with the graph viewer "dotty". Also outputs +// function declarations to stderr. +ASTConsumer *CreateASTViewer(); + +// DeclContext printer: prints out the DeclContext tree in human-readable form +// to stderr; this is intended for debugging. +ASTConsumer *CreateDeclContextPrinter(); + +// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code. +// This is considered experimental, and only works with Apple's ObjC runtime. +ASTConsumer *CreateObjCRewriter(const std::string &InFile, + llvm::raw_ostream *OS, + Diagnostic &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. +ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP, + bool SyntaxHighlight = true, + bool HighlightMacros = true); + +// PCH generator: generates a precompiled header file; this file can be used +// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile +// times. +ASTConsumer *CreatePCHGenerator(const Preprocessor &PP, + llvm::raw_ostream *OS, + const char *isysroot = 0); + +// Inheritance viewer: for C++ code, creates a graph of the inheritance +// tree for the given class and displays it with "dotty". +ASTConsumer *CreateInheritanceViewer(const std::string& clsname); + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h new file mode 100644 index 0000000..9252358 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h @@ -0,0 +1,266 @@ +//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ASTUnit utility class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H +#define LLVM_CLANG_FRONTEND_ASTUNIT_H + +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" +#include "clang/Basic/FileManager.h" +#include "clang/Index/ASTLocation.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/System/Path.h" +#include <map> +#include <string> +#include <vector> +#include <cassert> +#include <utility> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { +class ASTContext; +class CompilerInvocation; +class Decl; +class Diagnostic; +class FileEntry; +class FileManager; +class HeaderSearch; +class Preprocessor; +class SourceManager; +class TargetInfo; + +using namespace idx; + +/// \brief Utility class for loading a ASTContext from a PCH file. +/// +class ASTUnit { +public: + typedef std::map<FileID, std::vector<PreprocessedEntity *> > + PreprocessedEntitiesByFileMap; +private: + llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; + llvm::OwningPtr<FileManager> FileMgr; + llvm::OwningPtr<SourceManager> SourceMgr; + llvm::OwningPtr<HeaderSearch> HeaderInfo; + llvm::OwningPtr<TargetInfo> Target; + llvm::OwningPtr<Preprocessor> PP; + llvm::OwningPtr<ASTContext> Ctx; + + /// Optional owned invocation, just used to make the invocation used in + /// LoadFromCommandLine available. + llvm::OwningPtr<CompilerInvocation> Invocation; + + // OnlyLocalDecls - when true, walking this AST should only visit declarations + // that come from the AST itself, not from included precompiled headers. + // FIXME: This is temporary; eventually, CIndex will always do this. + bool OnlyLocalDecls; + + /// Track whether the main file was loaded from an AST or not. + bool MainFileIsAST; + + /// Track the top-level decls which appeared in an ASTUnit which was loaded + /// from a source file. + // + // FIXME: This is just an optimization hack to avoid deserializing large parts + // of a PCH file when using the Index library on an ASTUnit loaded from + // source. In the long term we should make the Index library use efficient and + // more scalable search mechanisms. + std::vector<Decl*> TopLevelDecls; + + /// The name of the original source file used to generate this ASTUnit. + std::string OriginalSourceFile; + + // Critical optimization when using clang_getCursor(). + ASTLocation LastLoc; + + /// \brief The set of diagnostics produced when creating this + /// translation unit. + llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics; + + /// \brief Temporary files that should be removed when the ASTUnit is + /// destroyed. + llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles; + + /// \brief A mapping from file IDs to the set of preprocessed entities + /// stored in that file. + /// + /// FIXME: This is just an optimization hack to avoid searching through + /// many preprocessed entities during cursor traversal in the CIndex library. + /// Ideally, we would just be able to perform a binary search within the + /// list of preprocessed entities. + PreprocessedEntitiesByFileMap PreprocessedEntitiesByFile; + + /// \brief Simple hack to allow us to assert that ASTUnit is not being + /// used concurrently, which is not supported. + /// + /// Clients should create instances of the ConcurrencyCheck class whenever + /// using the ASTUnit in a way that isn't intended to be concurrent, which is + /// just about any usage. + unsigned int ConcurrencyCheckValue; + static const unsigned int CheckLocked = 28573289; + static const unsigned int CheckUnlocked = 9803453; + + ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT + ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT + + explicit ASTUnit(bool MainFileIsAST); + +public: + class ConcurrencyCheck { + volatile ASTUnit &Self; + + public: + explicit ConcurrencyCheck(ASTUnit &Self) + : Self(Self) + { + assert(Self.ConcurrencyCheckValue == CheckUnlocked && + "Concurrent access to ASTUnit!"); + Self.ConcurrencyCheckValue = CheckLocked; + } + + ~ConcurrencyCheck() { + Self.ConcurrencyCheckValue = CheckUnlocked; + } + }; + friend class ConcurrencyCheck; + + ~ASTUnit(); + + bool isMainFileAST() const { return MainFileIsAST; } + + const Diagnostic &getDiagnostics() const { return *Diagnostics; } + Diagnostic &getDiagnostics() { return *Diagnostics; } + + const SourceManager &getSourceManager() const { return *SourceMgr; } + SourceManager &getSourceManager() { return *SourceMgr; } + + const Preprocessor &getPreprocessor() const { return *PP.get(); } + Preprocessor &getPreprocessor() { return *PP.get(); } + + const ASTContext &getASTContext() const { return *Ctx.get(); } + ASTContext &getASTContext() { return *Ctx.get(); } + + const FileManager &getFileManager() const { return *FileMgr; } + FileManager &getFileManager() { return *FileMgr; } + + const std::string &getOriginalSourceFileName(); + const std::string &getPCHFileName(); + + /// \brief Add a temporary file that the ASTUnit depends on. + /// + /// This file will be erased when the ASTUnit is destroyed. + void addTemporaryFile(const llvm::sys::Path &TempFile) { + TemporaryFiles.push_back(TempFile); + } + + bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + + void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } + ASTLocation getLastASTLocation() const { return LastLoc; } + + std::vector<Decl*> &getTopLevelDecls() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDecls; + } + const std::vector<Decl*> &getTopLevelDecls() const { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDecls; + } + + /// \brief Retrieve the mapping from File IDs to the preprocessed entities + /// within that file. + PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() { + return PreprocessedEntitiesByFile; + } + + // Retrieve the diagnostics associated with this AST + typedef const StoredDiagnostic *stored_diag_iterator; + stored_diag_iterator stored_diag_begin() const { + return StoredDiagnostics.begin(); + } + stored_diag_iterator stored_diag_end() const { + return StoredDiagnostics.end(); + } + unsigned stored_diag_size() const { return StoredDiagnostics.size(); } + + llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() { + return StoredDiagnostics; + } + + /// \brief A mapping from a file name to the memory buffer that stores the + /// remapped contents of that file. + typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; + + /// \brief Create a ASTUnit from a PCH file. + /// + /// \param Filename - The PCH file to load. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \returns - The initialized ASTUnit or null if the PCH failed to load. + static ASTUnit *LoadFromPCHFile(const std::string &Filename, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, + bool OnlyLocalDecls = false, + RemappedFile *RemappedFiles = 0, + unsigned NumRemappedFiles = 0, + bool CaptureDiagnostics = false); + + /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a + /// CompilerInvocation object. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + // + // 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<Diagnostic> Diags, + bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false); + + /// LoadFromCommandLine - Create an ASTUnit from a vector of command line + /// arguments, which must specify exactly one source file. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// + /// \param ArgEnd - The end of the argument vector. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \param ResourceFilesPath - The path to the compiler resource files. + // + // 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<Diagnostic> Diags, + llvm::StringRef ResourceFilesPath, + bool OnlyLocalDecls = false, + RemappedFile *RemappedFiles = 0, + unsigned NumRemappedFiles = 0, + bool CaptureDiagnostics = false); +}; + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def new file mode 100644 index 0000000..aaa3920 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def @@ -0,0 +1,85 @@ +//===-- Analyses.def - Metadata about Static Analyses -----------*- 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 set of static analyses used by AnalysisConsumer. +// +//===----------------------------------------------------------------------===// + +#ifndef ANALYSIS +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) +#endif + +ANALYSIS(CFGDump, "cfg-dump", + "Display Control-Flow Graphs", Code) + +ANALYSIS(CFGView, "cfg-view", + "View Control-Flow Graphs using GraphViz", Code) + +ANALYSIS(DisplayLiveVariables, "dump-live-variables", + "Print results of live variable analysis", Code) + +ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic", + "Perform quick security checks that require no data flow", Code) + +ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions", + "Check code for LLVM codebase conventions (domain-specific)", + TranslationUnit) + +ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores", + "Warn about stores to dead variables", Code) + +ANALYSIS(WarnUninitVals, "warn-uninit-values", + "Warn about uses of uninitialized variables", Code) + +ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs", + "Warn about Objective-C method signatures with type incompatibilities", + ObjCImplementation) + +ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc", +"Warn about Objective-C classes that lack a correct implementation of -dealloc", + ObjCImplementation) + +ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars", + "Warn about private ivars that are never used", ObjCImplementation) + +ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", + "Run the [Core] Foundation reference count checker", Code) + +ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer", + "Warn about unintended use of sizeof() on pointer expressions", Code) + +#ifndef ANALYSIS_STORE +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) +#endif + +ANALYSIS_STORE(BasicStore, "basic", "Use basic analyzer store", CreateBasicStoreManager) +ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager) +ANALYSIS_STORE(FlatStore, "flat", "Use flat analyzer store", CreateFlatStoreManager) + +#ifndef ANALYSIS_CONSTRAINTS +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) +#endif + +ANALYSIS_CONSTRAINTS(BasicConstraints, "basic", "Use basic constraint tracking", CreateBasicConstraintManager) +ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) + +#ifndef ANALYSIS_DIAGNOSTICS +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) +#endif + +ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", CreateHTMLDiagnosticClient, false) +ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", CreatePlistDiagnosticClient, true) +ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", CreatePlistHTMLDiagnosticClient, true) + +#undef ANALYSIS +#undef ANALYSIS_STORE +#undef ANALYSIS_CONSTRAINTS +#undef ANALYSIS_DIAGNOSTICS +#undef ANALYSIS_STORE + diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalysisConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalysisConsumer.h new file mode 100644 index 0000000..2cbdf36 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalysisConsumer.h @@ -0,0 +1,104 @@ +//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- 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 functions necessary for a front-end to run various +// analyses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H +#define LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H + +#include <string> +#include <vector> + +namespace clang { +class ASTConsumer; +class Diagnostic; +class Preprocessor; +class LangOptions; + +/// Analysis - Set of available source code analyses. +enum Analyses { +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, +#include "clang/Frontend/Analyses.def" +NumAnalyses +}; + +/// AnalysisStores - Set of available analysis store models. +enum AnalysisStores { +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "clang/Frontend/Analyses.def" +NumStores +}; + +/// AnalysisConstraints - Set of available constraint models. +enum AnalysisConstraints { +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "clang/Frontend/Analyses.def" +NumConstraints +}; + +/// AnalysisDiagClients - Set of available diagnostic clients for rendering +/// analysis results. +enum AnalysisDiagClients { +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME, +#include "clang/Frontend/Analyses.def" +NUM_ANALYSIS_DIAG_CLIENTS +}; + +class AnalyzerOptions { +public: + std::vector<Analyses> AnalysisList; + AnalysisStores AnalysisStoreOpt; + AnalysisConstraints AnalysisConstraintsOpt; + AnalysisDiagClients AnalysisDiagOpt; + std::string AnalyzeSpecificFunction; + unsigned MaxNodes; + unsigned MaxLoop; + unsigned AnalyzeAll : 1; + unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzeNestedBlocks : 1; + unsigned EagerlyAssume : 1; + unsigned PurgeDead : 1; + unsigned TrimGraph : 1; + unsigned VisualizeEGDot : 1; + unsigned VisualizeEGUbi : 1; + unsigned EnableExperimentalChecks : 1; + unsigned EnableExperimentalInternalChecks : 1; + unsigned InlineCall : 1; + +public: + AnalyzerOptions() { + AnalysisStoreOpt = BasicStoreModel; + AnalysisConstraintsOpt = RangeConstraintsModel; + AnalysisDiagOpt = PD_HTML; + AnalyzeAll = 0; + AnalyzerDisplayProgress = 0; + AnalyzeNestedBlocks = 0; + EagerlyAssume = 0; + PurgeDead = 1; + TrimGraph = 0; + VisualizeEGDot = 0; + VisualizeEGUbi = 0; + EnableExperimentalChecks = 0; + EnableExperimentalInternalChecks = 0; + } +}; + +/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code +/// analysis passes. (The set of analyses run is controlled by command-line +/// options.) +ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp, + const std::string &output, + const AnalyzerOptions& Opts); + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h new file mode 100644 index 0000000..2d5e128 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h @@ -0,0 +1,58 @@ +//===--- ChainedDiagnosticClient.h - Chain Diagnostic Clients ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H +#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { +class LangOptions; + +/// ChainedDiagnosticClient - Chain two diagnostic clients so that diagnostics +/// go to the first client and then the second. The first diagnostic client +/// should be the "primary" client, and will be used for computing whether the +/// diagnostics should be included in counts. +class ChainedDiagnosticClient : public DiagnosticClient { + llvm::OwningPtr<DiagnosticClient> Primary; + llvm::OwningPtr<DiagnosticClient> Secondary; + +public: + ChainedDiagnosticClient(DiagnosticClient *_Primary, + DiagnosticClient *_Secondary) { + Primary.reset(_Primary); + Secondary.reset(_Secondary); + } + + virtual void BeginSourceFile(const LangOptions &LO, + const Preprocessor *PP) { + Primary->BeginSourceFile(LO, PP); + Secondary->BeginSourceFile(LO, PP); + } + + virtual void EndSourceFile() { + Secondary->EndSourceFile(); + Primary->EndSourceFile(); + } + + virtual bool IncludeInDiagnosticCounts() const { + return Primary->IncludeInDiagnosticCounts(); + } + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info) { + Primary->HandleDiagnostic(DiagLevel, Info); + Secondary->HandleDiagnostic(DiagLevel, Info); + } +}; + +} // end namspace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenAction.h new file mode 100644 index 0000000..dfc117a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenAction.h @@ -0,0 +1,70 @@ +//===--- CodeGenAction.h - LLVM Code Generation Frontend Action -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/ADT/OwningPtr.h" + +namespace llvm { + class Module; +} + +namespace clang { + +class CodeGenAction : public ASTFrontendAction { +private: + unsigned Act; + llvm::OwningPtr<llvm::Module> TheModule; + +protected: + CodeGenAction(unsigned _Act); + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual void EndSourceFileAction(); + +public: + ~CodeGenAction(); + + /// takeModule - Take the generated LLVM module, for use after the action has + /// been run. The result may be null on failure. + llvm::Module *takeModule(); +}; + +class EmitAssemblyAction : public CodeGenAction { +public: + EmitAssemblyAction(); +}; + +class EmitBCAction : public CodeGenAction { +public: + EmitBCAction(); +}; + +class EmitLLVMAction : public CodeGenAction { +public: + EmitLLVMAction(); +}; + +class EmitLLVMOnlyAction : public CodeGenAction { +public: + EmitLLVMOnlyAction(); +}; + +class EmitCodeGenOnlyAction : public CodeGenAction { +public: + EmitCodeGenOnlyAction(); +}; + +class EmitObjAction : public CodeGenAction { +public: + EmitObjAction(); +}; + +} diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h new file mode 100644 index 0000000..bea468b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h @@ -0,0 +1,80 @@ + +//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Command line parsing for source locations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H +#define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { + +/// \brief A source location that has been parsed on the command line. +struct ParsedSourceLocation { + std::string FileName; + unsigned Line; + unsigned Column; + +public: + /// Construct a parsed source location from a string; the Filename is empty on + /// error. + static ParsedSourceLocation FromString(llvm::StringRef Str) { + ParsedSourceLocation PSL; + std::pair<llvm::StringRef, llvm::StringRef> ColSplit = Str.rsplit(':'); + std::pair<llvm::StringRef, llvm::StringRef> LineSplit = + ColSplit.first.rsplit(':'); + + // If both tail splits were valid integers, return success. + if (!ColSplit.second.getAsInteger(10, PSL.Column) && + !LineSplit.second.getAsInteger(10, PSL.Line)) + PSL.FileName = LineSplit.first; + + return PSL; + } +}; + +} + +namespace llvm { + namespace cl { + /// \brief Command-line option parser that parses source locations. + /// + /// Source locations are of the form filename:line:column. + template<> + class parser<clang::ParsedSourceLocation> + : public basic_parser<clang::ParsedSourceLocation> { + public: + inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue, + clang::ParsedSourceLocation &Val); + }; + + bool + parser<clang::ParsedSourceLocation>:: + parse(Option &O, StringRef ArgName, StringRef ArgValue, + clang::ParsedSourceLocation &Val) { + using namespace clang; + + Val = ParsedSourceLocation::FromString(ArgValue); + if (Val.FileName.empty()) { + errs() << "error: " + << "source location must be of the form filename:line:column\n"; + return true; + } + + return false; + } + } +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h new file mode 100644 index 0000000..06dc800 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h @@ -0,0 +1,589 @@ +//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ +#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ + +#include "clang/Frontend/CompilerInvocation.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/OwningPtr.h" +#include <cassert> +#include <list> +#include <string> + +namespace llvm { +class LLVMContext; +class raw_ostream; +class raw_fd_ostream; +class Timer; +} + +namespace clang { +class ASTContext; +class ASTConsumer; +class CodeCompleteConsumer; +class Diagnostic; +class DiagnosticClient; +class ExternalASTSource; +class FileManager; +class FrontendAction; +class Preprocessor; +class SourceManager; +class TargetInfo; + +/// CompilerInstance - Helper class for managing a single instance of the Clang +/// compiler. +/// +/// The CompilerInstance serves two purposes: +/// (1) It manages the various objects which are necessary to run the compiler, +/// for example the preprocessor, the target information, and the AST +/// context. +/// (2) It provides utility routines for constructing and manipulating the +/// common Clang objects. +/// +/// The compiler instance generally owns the instance of all the objects that it +/// manages. However, clients can still share objects by manually setting the +/// object and retaking ownership prior to destroying the CompilerInstance. +/// +/// The compiler instance is intended to simplify clients, but not to lock them +/// in to the compiler instance for everything. When possible, utility functions +/// come in two forms; a short form that reuses the CompilerInstance objects, +/// and a long form that takes explicit instances of any required objects. +class CompilerInstance { + /// The LLVM context used for this instance. + llvm::OwningPtr<llvm::LLVMContext> LLVMContext; + + /// The options used in this compiler instance. + llvm::OwningPtr<CompilerInvocation> Invocation; + + /// The diagnostics engine instance. + llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; + + /// The diagnostics client instance. + llvm::OwningPtr<DiagnosticClient> DiagClient; + + /// The target being compiled for. + llvm::OwningPtr<TargetInfo> Target; + + /// The file manager. + llvm::OwningPtr<FileManager> FileMgr; + + /// The source manager. + llvm::OwningPtr<SourceManager> SourceMgr; + + /// The preprocessor. + llvm::OwningPtr<Preprocessor> PP; + + /// The AST context. + llvm::OwningPtr<ASTContext> Context; + + /// The AST consumer. + llvm::OwningPtr<ASTConsumer> Consumer; + + /// The code completion consumer. + llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer; + + /// The frontend timer + llvm::OwningPtr<llvm::Timer> FrontendTimer; + + /// The list of active output files. + std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; + + void operator=(const CompilerInstance &); // DO NOT IMPLEMENT + CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT +public: + CompilerInstance(); + ~CompilerInstance(); + + /// @name High-Level Operations + /// { + + /// ExecuteAction - Execute the provided action against the compiler's + /// CompilerInvocation object. + /// + /// This function makes the following assumptions: + /// + /// - The invocation options should be initialized. This function does not + /// handle the '-help' or '-version' options, clients should handle those + /// directly. + /// + /// - The diagnostics engine should have already been created by the client. + /// + /// - No other CompilerInstance state should have been initialized (this is + /// an unchecked error). + /// + /// - Clients should have initialized any LLVM target features that may be + /// required. + /// + /// - Clients should eventually call llvm_shutdown() upon the completion of + /// this routine to ensure that any managed objects are properly destroyed. + /// + /// Note that this routine may write output to 'stderr'. + /// + /// \param Act - The action to execute. + /// \return - True on success. + // + // FIXME: This function should take the stream to write any debugging / + // verbose output to as an argument. + // + // FIXME: Eliminate the llvm_shutdown requirement, that should either be part + // of the context or else not CompilerInstance specific. + bool ExecuteAction(FrontendAction &Act); + + /// } + /// @name LLVM Context + /// { + + bool hasLLVMContext() const { return LLVMContext != 0; } + + llvm::LLVMContext &getLLVMContext() const { + assert(LLVMContext && "Compiler instance has no LLVM context!"); + return *LLVMContext; + } + + llvm::LLVMContext *takeLLVMContext() { return LLVMContext.take(); } + + /// setLLVMContext - Replace the current LLVM context and take ownership of + /// \arg Value. + void setLLVMContext(llvm::LLVMContext *Value); + + /// } + /// @name Compiler Invocation and Options + /// { + + bool hasInvocation() const { return Invocation != 0; } + + CompilerInvocation &getInvocation() { + assert(Invocation && "Compiler instance has no invocation!"); + return *Invocation; + } + + CompilerInvocation *takeInvocation() { return Invocation.take(); } + + /// setInvocation - Replace the current invocation; the compiler instance + /// takes ownership of \arg Value. + void setInvocation(CompilerInvocation *Value); + + /// } + /// @name Forwarding Methods + /// { + + AnalyzerOptions &getAnalyzerOpts() { + return Invocation->getAnalyzerOpts(); + } + const AnalyzerOptions &getAnalyzerOpts() const { + return Invocation->getAnalyzerOpts(); + } + + CodeGenOptions &getCodeGenOpts() { + return Invocation->getCodeGenOpts(); + } + const CodeGenOptions &getCodeGenOpts() const { + return Invocation->getCodeGenOpts(); + } + + DependencyOutputOptions &getDependencyOutputOpts() { + return Invocation->getDependencyOutputOpts(); + } + const DependencyOutputOptions &getDependencyOutputOpts() const { + return Invocation->getDependencyOutputOpts(); + } + + DiagnosticOptions &getDiagnosticOpts() { + return Invocation->getDiagnosticOpts(); + } + const DiagnosticOptions &getDiagnosticOpts() const { + return Invocation->getDiagnosticOpts(); + } + + FrontendOptions &getFrontendOpts() { + return Invocation->getFrontendOpts(); + } + const FrontendOptions &getFrontendOpts() const { + return Invocation->getFrontendOpts(); + } + + HeaderSearchOptions &getHeaderSearchOpts() { + return Invocation->getHeaderSearchOpts(); + } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return Invocation->getHeaderSearchOpts(); + } + + LangOptions &getLangOpts() { + return Invocation->getLangOpts(); + } + const LangOptions &getLangOpts() const { + return Invocation->getLangOpts(); + } + + PreprocessorOptions &getPreprocessorOpts() { + return Invocation->getPreprocessorOpts(); + } + const PreprocessorOptions &getPreprocessorOpts() const { + return Invocation->getPreprocessorOpts(); + } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return Invocation->getPreprocessorOutputOpts(); + } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return Invocation->getPreprocessorOutputOpts(); + } + + TargetOptions &getTargetOpts() { + return Invocation->getTargetOpts(); + } + const TargetOptions &getTargetOpts() const { + return Invocation->getTargetOpts(); + } + + /// } + /// @name Diagnostics Engine + /// { + + bool hasDiagnostics() const { return Diagnostics != 0; } + + Diagnostic &getDiagnostics() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return *Diagnostics; + } + + /// setDiagnostics - Replace the current diagnostics engine; the compiler + /// instance takes ownership of \arg Value. + void setDiagnostics(Diagnostic *Value); + + DiagnosticClient &getDiagnosticClient() const { + assert(DiagClient && "Compiler instance has no diagnostic client!"); + return *DiagClient; + } + + /// takeDiagnosticClient - Remove the current diagnostics client and give + /// ownership to the caller. + DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); } + + /// setDiagnosticClient - Replace the current diagnostics client; the compiler + /// instance takes ownership of \arg Value. + void setDiagnosticClient(DiagnosticClient *Value); + + /// } + /// @name Target Info + /// { + + bool hasTarget() const { return Target != 0; } + + TargetInfo &getTarget() const { + assert(Target && "Compiler instance has no target!"); + return *Target; + } + + /// takeTarget - Remove the current diagnostics engine and give ownership + /// to the caller. + TargetInfo *takeTarget() { return Target.take(); } + + /// setTarget - Replace the current diagnostics engine; the compiler + /// instance takes ownership of \arg Value. + void setTarget(TargetInfo *Value); + + /// } + /// @name File Manager + /// { + + bool hasFileManager() const { return FileMgr != 0; } + + FileManager &getFileManager() const { + assert(FileMgr && "Compiler instance has no file manager!"); + return *FileMgr; + } + + /// takeFileManager - Remove the current file manager and give ownership to + /// the caller. + FileManager *takeFileManager() { return FileMgr.take(); } + + /// setFileManager - Replace the current file manager; the compiler instance + /// takes ownership of \arg Value. + void setFileManager(FileManager *Value); + + /// } + /// @name Source Manager + /// { + + bool hasSourceManager() const { return SourceMgr != 0; } + + SourceManager &getSourceManager() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return *SourceMgr; + } + + /// takeSourceManager - Remove the current source manager and give ownership + /// to the caller. + SourceManager *takeSourceManager() { return SourceMgr.take(); } + + /// setSourceManager - Replace the current source manager; the compiler + /// instance takes ownership of \arg Value. + void setSourceManager(SourceManager *Value); + + /// } + /// @name Preprocessor + /// { + + bool hasPreprocessor() const { return PP != 0; } + + Preprocessor &getPreprocessor() const { + assert(PP && "Compiler instance has no preprocessor!"); + return *PP; + } + + /// takePreprocessor - Remove the current preprocessor and give ownership to + /// the caller. + Preprocessor *takePreprocessor() { return PP.take(); } + + /// setPreprocessor - Replace the current preprocessor; the compiler instance + /// takes ownership of \arg Value. + void setPreprocessor(Preprocessor *Value); + + /// } + /// @name ASTContext + /// { + + bool hasASTContext() const { return Context != 0; } + + ASTContext &getASTContext() const { + assert(Context && "Compiler instance has no AST context!"); + return *Context; + } + + /// takeASTContext - Remove the current AST context and give ownership to the + /// caller. + ASTContext *takeASTContext() { return Context.take(); } + + /// setASTContext - Replace the current AST context; the compiler instance + /// takes ownership of \arg Value. + void setASTContext(ASTContext *Value); + + /// } + /// @name ASTConsumer + /// { + + bool hasASTConsumer() const { return Consumer != 0; } + + ASTConsumer &getASTConsumer() const { + assert(Consumer && "Compiler instance has no AST consumer!"); + return *Consumer; + } + + /// takeASTConsumer - Remove the current AST consumer and give ownership to + /// the caller. + ASTConsumer *takeASTConsumer() { return Consumer.take(); } + + /// setASTConsumer - Replace the current AST consumer; the compiler instance + /// takes ownership of \arg Value. + void setASTConsumer(ASTConsumer *Value); + + /// } + /// @name Code Completion + /// { + + bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; } + + CodeCompleteConsumer &getCodeCompletionConsumer() const { + assert(CompletionConsumer && + "Compiler instance has no code completion consumer!"); + return *CompletionConsumer; + } + + /// takeCodeCompletionConsumer - Remove the current code completion consumer + /// and give ownership to the caller. + CodeCompleteConsumer *takeCodeCompletionConsumer() { + return CompletionConsumer.take(); + } + + /// setCodeCompletionConsumer - Replace the current code completion consumer; + /// the compiler instance takes ownership of \arg Value. + void setCodeCompletionConsumer(CodeCompleteConsumer *Value); + + /// } + /// @name Frontend timer + /// { + + bool hasFrontendTimer() const { return FrontendTimer != 0; } + + llvm::Timer &getFrontendTimer() const { + assert(FrontendTimer && "Compiler instance has no frontend timer!"); + return *FrontendTimer; + } + + /// } + /// @name Output Files + /// { + + /// getOutputFileList - Get the list of (path, output stream) pairs of output + /// files; the path may be empty but the stream will always be non-null. + const std::list< std::pair<std::string, + llvm::raw_ostream*> > &getOutputFileList() const; + + /// addOutputFile - Add an output file onto the list of tracked output files. + /// + /// \param Path - The path to the output file, or empty. + /// \param OS - The output stream, which should be non-null. + void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS); + + /// clearOutputFiles - Clear the output file list, destroying the contained + /// output streams. + /// + /// \param EraseFiles - If true, attempt to erase the files from disk. + void clearOutputFiles(bool EraseFiles); + + /// } + /// @name Construction Utility Methods + /// { + + /// Create the diagnostics engine using the invocation's diagnostic options + /// and replace any existing one with it. + /// + /// Note that this routine also replaces the diagnostic client. + void createDiagnostics(int Argc, char **Argv); + + /// Create a Diagnostic object with a the TextDiagnosticPrinter. + /// + /// The \arg Argc and \arg Argv arguments are used only for logging purposes, + /// when the diagnostic options indicate that the compiler should output + /// logging information. + /// + /// Note that this creates an unowned DiagnosticClient, if using directly the + /// caller is responsible for releasing the returned Diagnostic's client + /// eventually. + /// + /// \param Opts - The diagnostic options; note that the created text + /// diagnostic object contains a reference to these options and its lifetime + /// must extend past that of the diagnostic engine. + /// + /// \return The new object on success, or null on failure. + static llvm::IntrusiveRefCntPtr<Diagnostic> + createDiagnostics(const DiagnosticOptions &Opts, int Argc, char **Argv); + + /// Create the file manager and replace any existing one with it. + void createFileManager(); + + /// Create the source manager and replace any existing one with it. + void createSourceManager(); + + /// Create the preprocessor, using the invocation, file, and source managers, + /// and replace any existing one with it. + void createPreprocessor(); + + /// Create a Preprocessor object. + /// + /// Note that this also creates a new HeaderSearch object which will be owned + /// by the resulting Preprocessor. + /// + /// \return The new object on success, or null on failure. + static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &, + const PreprocessorOptions &, + const HeaderSearchOptions &, + const DependencyOutputOptions &, + const TargetInfo &, + const FrontendOptions &, + SourceManager &, FileManager &); + + /// Create the AST context. + void createASTContext(); + + /// Create an external AST source to read a PCH file and attach it to the AST + /// context. + void createPCHExternalASTSource(llvm::StringRef Path); + + /// Create an external AST source to read a PCH file. + /// + /// \return - The new object on success, or null on failure. + static ExternalASTSource * + createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, + Preprocessor &PP, ASTContext &Context); + + /// Create a code completion consumer using the invocation; note that this + /// will cause the source manager to truncate the input source file at the + /// completion point. + void createCodeCompletionConsumer(); + + /// Create a code completion consumer to print code completion results, at + /// \arg Filename, \arg Line, and \arg Column, to the given output stream \arg + /// OS. + static CodeCompleteConsumer * + createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, + unsigned Line, unsigned Column, + bool UseDebugPrinter, bool ShowMacros, + bool ShowCodePatterns, llvm::raw_ostream &OS); + + /// Create the frontend timer and replace any existing one with it. + void createFrontendTimer(); + + /// Create the default output file (from the invocation's options) and add it + /// to the list of tracked output files. + /// + /// \return - Null on error. + llvm::raw_fd_ostream * + createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "", + llvm::StringRef Extension = ""); + + /// Create a new output file and add it to the list of tracked output files, + /// optionally deriving the output path name. + /// + /// \return - Null on error. + llvm::raw_fd_ostream * + createOutputFile(llvm::StringRef OutputPath, bool Binary = true, + llvm::StringRef BaseInput = "", + llvm::StringRef Extension = ""); + + /// Create a new output file, optionally deriving the output path name. + /// + /// If \arg OutputPath is empty, then createOutputFile will derive an output + /// path location as \arg BaseInput, with any suffix removed, and \arg + /// Extension appended. + /// + /// \param OutputPath - If given, the path to the output file. + /// \param Error [out] - On failure, the error message. + /// \param BaseInput - If \arg OutputPath is empty, the input path name to use + /// for deriving the output path. + /// \param Extension - The extension to use for derived output names. + /// \param Binary - The mode to open the file in. + /// \param ResultPathName [out] - If given, the result path name will be + /// stored here on success. + static llvm::raw_fd_ostream * + createOutputFile(llvm::StringRef OutputPath, std::string &Error, + bool Binary = true, llvm::StringRef BaseInput = "", + llvm::StringRef Extension = "", + std::string *ResultPathName = 0); + + /// } + /// @name Initialization Utility Methods + /// { + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + bool InitializeSourceManager(llvm::StringRef InputFile); + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + static bool InitializeSourceManager(llvm::StringRef InputFile, + Diagnostic &Diags, + FileManager &FileMgr, + SourceManager &SourceMgr, + const FrontendOptions &Opts); + + /// } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h new file mode 100644 index 0000000..f5a9053 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h @@ -0,0 +1,162 @@ +//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ +#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ + +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/CodeGen/CodeGenOptions.h" +#include "clang/Frontend/AnalysisConsumer.h" +#include "clang/Frontend/DependencyOutputOptions.h" +#include "clang/Frontend/DiagnosticOptions.h" +#include "clang/Frontend/FrontendOptions.h" +#include "clang/Frontend/HeaderSearchOptions.h" +#include "clang/Frontend/PreprocessorOptions.h" +#include "clang/Frontend/PreprocessorOutputOptions.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include <string> +#include <vector> + +namespace llvm { + template<typename T> class SmallVectorImpl; +} + +namespace clang { + +class Diagnostic; + +/// 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 { + /// Options controlling the static analyzer. + AnalyzerOptions AnalyzerOpts; + + /// Options controlling IRgen and the backend. + CodeGenOptions CodeGenOpts; + + /// Options controlling dependency output. + DependencyOutputOptions DependencyOutputOpts; + + /// Options controlling the diagnostic engine. + DiagnosticOptions DiagnosticOpts; + + /// Options controlling the frontend itself. + FrontendOptions FrontendOpts; + + /// Options controlling the #include directive. + HeaderSearchOptions HeaderSearchOpts; + + /// Options controlling the language variant. + LangOptions LangOpts; + + /// Options controlling the preprocessor (aside from #include handling). + PreprocessorOptions PreprocessorOpts; + + /// Options controlling preprocessed output. + PreprocessorOutputOptions PreprocessorOutputOpts; + + /// Options controlling the target. + TargetOptions TargetOpts; + +public: + CompilerInvocation() {} + + /// @name Utility Methods + /// @{ + + /// CreateFromArgs - Create a compiler invocation from a list of input + /// options. + /// + /// \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, const char **ArgBegin, + const char **ArgEnd, Diagnostic &Diags); + + /// GetBuiltinIncludePath - Get the directory where the compiler headers + /// reside, relative to the compiler binary (found by the passed in + /// arguments). + /// + /// \param Argv0 - The program path (from argv[0]), for finding the builtin + /// compiler path. + /// \param MainAddr - The address of main (or some other function in the main + /// executable), for finding the builtin compiler path. + static std::string GetResourcesPath(const char *Argv0, void *MainAddr); + + /// toArgs - Convert the CompilerInvocation to a list of strings suitable for + /// passing to CreateFromArgs. + void toArgs(std::vector<std::string> &Res); + + /// @} + /// @name Option Subgroups + /// @{ + + AnalyzerOptions &getAnalyzerOpts() { return AnalyzerOpts; } + const AnalyzerOptions &getAnalyzerOpts() const { + return AnalyzerOpts; + } + + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } + const CodeGenOptions &getCodeGenOpts() const { + return CodeGenOpts; + } + + DependencyOutputOptions &getDependencyOutputOpts() { + return DependencyOutputOpts; + } + const DependencyOutputOptions &getDependencyOutputOpts() const { + return DependencyOutputOpts; + } + + DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; } + const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; } + + HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return HeaderSearchOpts; + } + + FrontendOptions &getFrontendOpts() { return FrontendOpts; } + const FrontendOptions &getFrontendOpts() const { + return FrontendOpts; + } + + LangOptions &getLangOpts() { return LangOpts; } + const LangOptions &getLangOpts() const { return LangOpts; } + + PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; } + const PreprocessorOptions &getPreprocessorOpts() const { + return PreprocessorOpts; + } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return PreprocessorOutputOpts; + } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return PreprocessorOutputOpts; + } + + TargetOptions &getTargetOpts() { return TargetOpts; } + const TargetOptions &getTargetOpts() const { + return TargetOpts; + } + + /// @} +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def new file mode 100644 index 0000000..39ed5f9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def @@ -0,0 +1,113 @@ +//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- 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 XML context info database as written in the +// <ReferenceSection>/<Contexts> sub-nodes of the XML document. Type nodes +// are referred by "context" reference attributes throughout the document. +// A context node never contains sub-nodes. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// context of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that context +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by "context" attributes to this value. +// +// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type +// nodes by a "type" attribute, if they create a type during declaration. +// For instance 'struct S;' creates both a context 'S::' and a type 'S'. +// Contexts and types always have different ids, however declarations and +// contexts may share the same ids. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +//===----------------------------------------------------------------------===// + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +NODE_XML(TranslationUnitDecl, "TranslationUnit") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(FunctionDecl, "Function") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()) +END_NODE_XML + +NODE_XML(NamespaceDecl, "Namespace") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(RecordDecl, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getTypeForDecl()) +END_NODE_XML + +NODE_XML(EnumDecl, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getTypeForDecl()) +END_NODE_XML + +NODE_XML(LinkageSpecDecl, "LinkageSpec") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") + ENUM_XML(LinkageSpecDecl::lang_c, "C") + ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") + END_ENUM_XML +END_NODE_XML + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def new file mode 100644 index 0000000..16551ee --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def @@ -0,0 +1,367 @@ +//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- 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 XML statement database structure as written in +// <TranslationUnit> sub-nodes of the XML document. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by reference attributes to this value (currently used only for Label). +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an +// expression by a "type" attribute. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of +// a statement in the source file(s). +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef ATTRIBUTE_FILE_LOCATION_XML +# define ATTRIBUTE_FILE_LOCATION_XML \ + ATTRIBUTE_XML(getFilename(), "file") \ + ATTRIBUTE_XML(getLine(), "line") \ + ATTRIBUTE_XML(getColumn(), "col") \ + ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ + ATTRIBUTE_OPT_XML(getLine(), "endline") \ + ATTRIBUTE_OPT_XML(getColumn(), "endcol") +#endif + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +//NODE_XML(TranslationUnitDecl, "TranslationUnit") +// SUB_NODE_SEQUENCE_XML(Decl) +//END_NODE_XML + +NODE_XML(Decl, "FIXME_Decl") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclKindName(), "unhandled_decl_name") +END_NODE_XML + +NODE_XML(FunctionDecl, "Function") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") + ENUM_XML(FunctionDecl::None, "") + ENUM_XML(FunctionDecl::Extern, "extern") + ENUM_XML(FunctionDecl::Static, "static") + ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__") + END_ENUM_XML + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXMethodDecl, "CXXMethod") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXConstructorDecl, "CXXConstructor") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") + ATTRIBUTE_OPT_XML(isDefaultConstructor(), "is_default_ctor") + ATTRIBUTE_OPT_XML(isCopyConstructor(), "is_copy_ctor") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXDestructorDecl, "CXXDestructor") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXConversionDecl, "CXXConversion") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(NamespaceDecl, "Namespace") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + SUB_NODE_SEQUENCE_XML(DeclContext) +END_NODE_XML + +NODE_XML(UsingDirectiveDecl, "UsingDirective") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_XML(getNominatedNamespace(), "ref") +END_NODE_XML + +NODE_XML(NamespaceAliasDecl, "NamespaceAlias") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_XML(getNamespace(), "ref") +END_NODE_XML + +NODE_XML(RecordDecl, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates + SUB_NODE_SEQUENCE_XML(FieldDecl) +END_NODE_XML + +NODE_XML(CXXRecordDecl, "CXXRecord") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates + SUB_NODE_SEQUENCE_XML(FieldDecl) +END_NODE_XML + +NODE_XML(EnumDecl, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") + ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling + SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition +END_NODE_XML + +NODE_XML(EnumConstantDecl, "EnumConstant") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer + SUB_NODE_OPT_XML(Expr) // init expr of this constant +END_NODE_XML + +NODE_XML(FieldDecl, "Field") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_OPT_XML(isMutable(), "mutable") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_OPT_XML(isBitField(), "bitfield") + SUB_NODE_OPT_XML(Expr) // init expr of a bit field +END_NODE_XML + +NODE_XML(TypedefDecl, "Typedef") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getUnderlyingType()) +END_NODE_XML + +NODE_XML(VarDecl, "Var") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") + ENUM_XML(VarDecl::None, "") + ENUM_XML(VarDecl::Auto, "auto") + ENUM_XML(VarDecl::Register, "register") + ENUM_XML(VarDecl::Extern, "extern") + ENUM_XML(VarDecl::Static, "static") + ENUM_XML(VarDecl::PrivateExtern, "__private_extern__") + END_ENUM_XML + SUB_NODE_OPT_XML(Expr) // init expr +END_NODE_XML + +NODE_XML(ParmVarDecl, "ParmVar") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_OPT_XML(Expr) // default argument expression +END_NODE_XML + +NODE_XML(LinkageSpecDecl, "LinkageSpec") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") + ENUM_XML(LinkageSpecDecl::lang_c, "C") + ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") + END_ENUM_XML +END_NODE_XML + +NODE_XML(TemplateDecl, "Template") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(TemplateTypeParmDecl, "TemplateTypeParm") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(UsingShadowDecl, "UsingShadow") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getTargetDecl(), "target_decl") + ATTRIBUTE_XML(getUsingDecl(), "using_decl") +END_NODE_XML + +NODE_XML(UsingDecl, "Using") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl") + ATTRIBUTE_XML(isTypeName(), "is_typename") +END_NODE_XML + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML +#undef SUB_NODE_FN_BODY_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h new file mode 100644 index 0000000..ab8e49d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h @@ -0,0 +1,43 @@ +//===--- DependencyOutputOptions.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// DependencyOutputOptions - Options for controlling the compiler dependency +/// file generation. +class DependencyOutputOptions { +public: + unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies. + unsigned UsePhonyTargets : 1; ///< Include phony targets for each + /// dependency, which can avoid some 'make' + /// problems. + + /// The file to write depencency output to. + std::string OutputFile; + + /// A list of names to use as the targets in the dependency file; this list + /// must contain at least one entry. + std::vector<std::string> Targets; + +public: + DependencyOutputOptions() { + IncludeSystemHeaders = 0; + UsePhonyTargets = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h new file mode 100644 index 0000000..8eb66e5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h @@ -0,0 +1,91 @@ +//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H +#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// DiagnosticOptions - Options for controlling the compiler diagnostics +/// engine. +class DiagnosticOptions { +public: + unsigned IgnoreWarnings : 1; /// -w + unsigned NoRewriteMacros : 1; /// -Wno-rewrite-macros + unsigned Pedantic : 1; /// -pedantic + unsigned PedanticErrors : 1; /// -pedantic-errors + unsigned ShowColumn : 1; /// Show column number on diagnostics. + unsigned ShowLocation : 1; /// Show source location information. + unsigned ShowCarets : 1; /// Show carets in diagnostics. + unsigned ShowFixits : 1; /// Show fixit information. + unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. + unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable + /// diagnostics. + unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, + /// 2 -> Full Name. + unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. + unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected + /// diagnostics, indicated by markers in the + /// input source file. + unsigned BinaryOutput : 1; /// Emit diagnostics via the diagnostic + /// binary serialization mechanism, to be + /// deserialized by, e.g., the CIndex library. + + unsigned ErrorLimit; /// Limit # errors emitted. + unsigned MacroBacktraceLimit; /// Limit depth of macro instantiation + /// backtrace. + unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. + + /// The distance between tab stops. + unsigned TabStop; + enum { DefaultTabStop = 8, MaxTabStop = 100, + DefaultMacroBacktraceLimit = 6, + DefaultTemplateBacktraceLimit = 10 }; + + /// Column limit for formatting message diagnostics, or 0 if unused. + unsigned MessageLength; + + /// If non-empty, a file to log extended build information to, for development + /// testing and analysis. + std::string DumpBuildInformation; + + /// The list of -W... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector<std::string> Warnings; + +public: + DiagnosticOptions() { + IgnoreWarnings = 0; + TabStop = DefaultTabStop; + MessageLength = 0; + NoRewriteMacros = 0; + Pedantic = 0; + PedanticErrors = 0; + ShowCarets = 1; + ShowColors = 0; + ShowColumn = 1; + ShowFixits = 1; + ShowLocation = 1; + ShowOptionNames = 0; + ShowCategories = 0; + ShowSourceRanges = 0; + VerifyDiagnostics = 0; + BinaryOutput = 0; + ErrorLimit = 0; + TemplateBacktraceLimit = DefaultTemplateBacktraceLimit; + MacroBacktraceLimit = DefaultMacroBacktraceLimit; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def new file mode 100644 index 0000000..4c52bd8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def @@ -0,0 +1,75 @@ +//===-- DocumentXML.def - Metadata about Document XML nodes -----*- 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 XML root database structure as written in +// an AST XML document. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a +// string, which value uniquely identify the entity represented by that node. +// Other nodes may refer by reference attributes to this value. +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +ROOT_NODE_XML("CLANG_XML") + ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed + SUB_NODE_XML("TranslationUnit") + SUB_NODE_XML("ReferenceSection") +END_NODE_XML + +NODE_XML("TranslationUnit") + SUB_NODE_SEQUENCE_XML(Decl) +END_NODE_XML + +NODE_XML("ReferenceSection") + SUB_NODE_XML("Types") + SUB_NODE_XML("Contexts") + SUB_NODE_XML("Files") +END_NODE_XML + +NODE_XML("Types") + SUB_NODE_SEQUENCE_XML(Type) +END_NODE_XML + +NODE_XML("Contexts") + SUB_NODE_SEQUENCE_XML(DeclContext) +END_NODE_XML + +NODE_XML("Files") + SUB_NODE_SEQUENCE_XML("File") +END_NODE_XML + +NODE_XML("File") + ID_ATTRIBUTE_XML + ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name +END_NODE_XML + + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h new file mode 100644 index 0000000..73d8921 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h @@ -0,0 +1,186 @@ +//===--- DocumentXML.h - XML document for ASTs ------------------*- 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 XML document class, which provides the means to +// dump out the AST in a XML form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H +#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H + +#include <string> +#include <map> +#include <stack> +#include "clang/AST/Type.h" +#include "clang/AST/TypeOrdering.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +//--------------------------------------------------------- forwards +class DeclContext; +class Decl; +class NamedDecl; +class FunctionDecl; +class ASTContext; +class LabelStmt; + +//--------------------------------------------------------- +namespace XML { + // id maps: + template<class T> + struct IdMap : llvm::DenseMap<T, unsigned> {}; + + template<> + struct IdMap<QualType> : std::map<QualType, unsigned, QualTypeOrdering> {}; + + template<> + struct IdMap<std::string> : std::map<std::string, unsigned> {}; +} + +//--------------------------------------------------------- +class DocumentXML { +public: + DocumentXML(const std::string& rootName, llvm::raw_ostream& out); + + void initialize(ASTContext &Context); + void PrintDecl(Decl *D); + void PrintStmt(const Stmt *S); // defined in StmtXML.cpp + void finalize(); + + + DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this + DocumentXML& toParent(); // returns *this + + void addAttribute(const char* pName, const QualType& pType); + void addAttribute(const char* pName, bool value); + + template<class T> + void addAttribute(const char* pName, const T* value) { + addPtrAttribute(pName, value); + } + + template<class T> + void addAttribute(const char* pName, T* value) { + addPtrAttribute(pName, value); + } + + template<class T> + void addAttribute(const char* pName, const T& value); + + template<class T> + void addAttributeOptional(const char* pName, const T& value); + + void addSourceFileAttribute(const std::string& fileName); + + PresumedLoc addLocation(const SourceLocation& Loc); + void addLocationRange(const SourceRange& R); + + static std::string escapeString(const char* pStr, std::string::size_type len); + +private: + DocumentXML(const DocumentXML&); // not defined + DocumentXML& operator=(const DocumentXML&); // not defined + + std::stack<std::string> NodeStack; + llvm::raw_ostream& Out; + ASTContext *Ctx; + bool HasCurrentNodeSubNodes; + + + XML::IdMap<QualType> Types; + XML::IdMap<const DeclContext*> Contexts; + XML::IdMap<const Type*> BasicTypes; + XML::IdMap<std::string> SourceFiles; + XML::IdMap<const NamedDecl*> Decls; + XML::IdMap<const LabelStmt*> Labels; + + void addContextsRecursively(const DeclContext *DC); + void addTypeRecursively(const Type* pType); + void addTypeRecursively(const QualType& pType); + + void Indent(); + + // forced pointer dispatch: + void addPtrAttribute(const char* pName, const Type* pType); + void addPtrAttribute(const char* pName, const NamedDecl* D); + void addPtrAttribute(const char* pName, const DeclContext* D); + void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation + void addPtrAttribute(const char* pName, const NestedNameSpecifier* N); + void addPtrAttribute(const char* pName, const LabelStmt* L); + void addPtrAttribute(const char* pName, const char* text); + + // defined in TypeXML.cpp: + void addParentTypes(const Type* pType); + void writeTypeToXML(const Type* pType); + void writeTypeToXML(const QualType& pType); + class TypeAdder; + friend class TypeAdder; + + // defined in DeclXML.cpp: + void writeDeclToXML(Decl *D); + class DeclPrinter; + friend class DeclPrinter; + + // for addAttributeOptional: + static bool isDefault(unsigned value) { return value == 0; } + static bool isDefault(bool value) { return !value; } + static bool isDefault(Qualifiers::GC value) { return value == Qualifiers::GCNone; } + static bool isDefault(const std::string& value) { return value.empty(); } +}; + +//--------------------------------------------------------- inlines + +inline void DocumentXML::initialize(ASTContext &Context) { + Ctx = &Context; +} + +//--------------------------------------------------------- +template<class T> +inline void DocumentXML::addAttribute(const char* pName, const T& value) { + std::string repr; + { + llvm::raw_string_ostream buf(repr); + buf << value; + buf.flush(); + } + + Out << ' ' << pName << "=\"" + << DocumentXML::escapeString(repr.c_str(), repr.size()) + << "\""; +} + +//--------------------------------------------------------- +inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) { + Out << ' ' << pName << "=\"" + << DocumentXML::escapeString(text, strlen(text)) + << "\""; +} + +//--------------------------------------------------------- +inline void DocumentXML::addAttribute(const char* pName, bool value) { + addPtrAttribute(pName, value ? "1" : "0"); +} + +//--------------------------------------------------------- +template<class T> +inline void DocumentXML::addAttributeOptional(const char* pName, + const T& value) { + if (!isDefault(value)) { + addAttribute(pName, value); + } +} + +//--------------------------------------------------------- + +} //namespace clang + +#endif //LLVM_CLANG_DOCUMENTXML_H diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Frontend/FixItRewriter.h new file mode 100644 index 0000000..b432d74 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FixItRewriter.h @@ -0,0 +1,104 @@ +//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- 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 diagnostic client adaptor that performs rewrites as +// suggested by code modification hints attached to diagnostics. It +// then forwards any diagnostics to the adapted diagnostic client. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H +#define LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Rewrite/Rewriter.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { class raw_ostream; } + +namespace clang { + +class SourceManager; +class FileEntry; + +class FixItPathRewriter { +public: + virtual ~FixItPathRewriter(); + + /// \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; +}; + +class FixItRewriter : public DiagnosticClient { + /// \brief The diagnostics machinery. + Diagnostic &Diags; + + /// \brief The rewriter used to perform the various code + /// modifications. + Rewriter Rewrite; + + /// \brief The diagnostic client that performs the actual formatting + /// of error messages. + DiagnosticClient *Client; + + /// \brief Turn an input path into an output path. NULL implies overwriting + /// the original. + FixItPathRewriter *PathRewriter; + + /// \brief The number of rewriter failures. + unsigned NumFailures; + +public: + typedef Rewriter::buffer_iterator iterator; + + /// \brief Initialize a new fix-it rewriter. + FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, + const LangOptions &LangOpts, FixItPathRewriter *PathRewriter); + + /// \brief Destroy the fix-it rewriter. + ~FixItRewriter(); + + /// \brief Check whether there are modifications for a given file. + bool IsModified(FileID ID) const { + return Rewrite.getRewriteBufferFor(ID) != NULL; + } + + // Iteration over files with changes. + iterator buffer_begin() { return Rewrite.buffer_begin(); } + iterator buffer_end() { return Rewrite.buffer_end(); } + + /// \brief Write a single modified source file. + /// + /// \returns true if there was an error, false otherwise. + bool WriteFixedFile(FileID ID, llvm::raw_ostream &OS); + + /// \brief Write the modified source files. + /// + /// \returns true if there was an error, false otherwise. + bool WriteFixedFiles(); + + /// IncludeInDiagnosticCounts - This method (whose default implementation + /// returns true) indicates whether the diagnostics handled by this + /// DiagnosticClient should be included in the number of diagnostics + /// reported by Diagnostic. + virtual bool IncludeInDiagnosticCounts() const; + + /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or + /// capturing it to a log as needed. + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + + /// \brief Emit a diagnostic via the adapted diagnostic client. + void Diag(FullSourceLoc Loc, unsigned DiagID); +}; + +} + +#endif // LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h new file mode 100644 index 0000000..7b7db37 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h @@ -0,0 +1,204 @@ +//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/OwningPtr.h" +#include <string> + +namespace clang { +class ASTUnit; +class ASTConsumer; +class CompilerInstance; +class ASTMergeAction; + +/// FrontendAction - Abstract base class for actions which can be performed by +/// the frontend. +class FrontendAction { + std::string CurrentFile; + llvm::OwningPtr<ASTUnit> CurrentASTUnit; + CompilerInstance *Instance; + friend class ASTMergeAction; + +protected: + /// @name Implementation Action Interface + /// @{ + + /// CreateASTConsumer - Create the AST consumer object for this action, if + /// supported. + /// + /// This routine is called as part of \see BeginSourceAction(), which will + /// fail if the AST consumer cannot be created. This will not be called if the + /// action has indicated that it only uses the preprocessor. + /// + /// \param CI - The current compiler instance, provided as a convenience, \see + /// getCompilerInstance(). + /// + /// \param InFile - The current input file, provided as a convenience, \see + /// getCurrentFile(). + /// + /// \return The new AST consumer, or 0 on failure. + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) = 0; + + /// BeginSourceFileAction - Callback at the start of processing a single + /// input. + /// + /// \return True on success; on failure \see ExecutionAction() and + /// EndSourceFileAction() will not be called. + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename) { + return true; + } + + /// ExecuteAction - Callback to run the program action, using the initialized + /// compiler instance. + /// + /// This routine is guaranteed to only be called between \see + /// BeginSourceFileAction() and \see EndSourceFileAction(). + virtual void ExecuteAction() = 0; + + /// 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). + virtual void EndSourceFileAction() {} + + /// @} + +public: + FrontendAction(); + virtual ~FrontendAction(); + + /// @name Compiler Instance Access + /// @{ + + CompilerInstance &getCompilerInstance() const { + assert(Instance && "Compiler instance not registered!"); + return *Instance; + } + + void setCompilerInstance(CompilerInstance *Value) { Instance = Value; } + + /// @} + /// @name Current File Information + /// @{ + + bool isCurrentFileAST() const { + assert(!CurrentFile.empty() && "No current file!"); + return CurrentASTUnit != 0; + } + + const std::string &getCurrentFile() const { + assert(!CurrentFile.empty() && "No current file!"); + return CurrentFile; + } + + ASTUnit &getCurrentASTUnit() const { + assert(!CurrentASTUnit && "No current AST unit!"); + return *CurrentASTUnit; + } + + ASTUnit *takeCurrentASTUnit() { + return CurrentASTUnit.take(); + } + + void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0); + + /// @} + /// @name Supported Modes + /// @{ + + /// usesPreprocessorOnly - Does this action only use the preprocessor? If so + /// no AST context will be created and this action will be invalid with PCH + /// inputs. + virtual bool usesPreprocessorOnly() const = 0; + + /// usesCompleteTranslationUnit - For AST based actions, should the + /// translation unit be completed? + virtual bool usesCompleteTranslationUnit() { return true; } + + /// hasPCHSupport - Does this action support use with PCH? + virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); } + + /// hasASTSupport - Does this action support use with AST files? + virtual bool hasASTSupport() const { return !usesPreprocessorOnly(); } + + /// hasCodeCompletionSupport - Does this action support use with code + /// completion? + virtual bool hasCodeCompletionSupport() const { return false; } + + /// @} + /// @name Public Action Interface + /// @{ + + /// BeginSourceFile - Prepare the action for processing the input file \arg + /// Filename; this is run after the options and frontend have been + /// initialized, but prior to executing any per-file processing. + /// + /// \param CI - The compiler instance this action is being run from. The + /// 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 IsAST - Indicates whether this is an AST input. AST inputs require + /// special handling, since the AST file itself contains several objects which + /// would normally be owned by the CompilerInstance. When processing AST input + /// files, these objects should generally not be initialized in the + /// CompilerInstance -- they will 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, llvm::StringRef Filename, + bool IsAST = false); + + /// Execute - Set the source managers main input file, and run the action. + void Execute(); + + /// EndSourceFile - Perform any per-file post processing, deallocate per-file + /// objects, and run statistics and output file cleanup code. + void EndSourceFile(); + + /// @} +}; + +/// ASTFrontendAction - Abstract base class to use for AST consumer based +/// frontend actions. +class ASTFrontendAction : public FrontendAction { + /// ExecuteAction - Implement the ExecuteAction interface by running Sema on + /// the already initialized AST consumer. + /// + /// This will also take care of instantiating a code completion consumer if + /// the user requested it and the action supports it. + virtual void ExecuteAction(); + +public: + virtual bool usesPreprocessorOnly() const { return false; } +}; + +/// PreprocessorFrontendAction - Abstract base class to use for preprocessor +/// based frontend actions. +class PreprocessorFrontendAction : public FrontendAction { +protected: + /// CreateASTConsumer - Provide a default implementation which returns aborts, + /// this method should never be called by FrontendAction clients. + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + +public: + virtual bool usesPreprocessorOnly() const { return true; } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h new file mode 100644 index 0000000..cee1c1d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h @@ -0,0 +1,230 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" +#include <string> +#include <vector> + +namespace clang { +class FixItRewriter; +class FixItPathRewriter; + +//===----------------------------------------------------------------------===// +// Custom Consumer Actions +//===----------------------------------------------------------------------===// + +class InitOnlyAction : public FrontendAction { + virtual void ExecuteAction(); + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + +public: + // Don't claim to only use the preprocessor, we want to follow the AST path, + // but do nothing. + virtual bool usesPreprocessorOnly() const { return false; } +}; + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class AnalysisAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTPrintXMLAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTDumpAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTViewAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class DeclContextPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class FixItAction : public ASTFrontendAction { +protected: + llvm::OwningPtr<FixItRewriter> Rewriter; + llvm::OwningPtr<FixItPathRewriter> PathRewriter; + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + + virtual void EndSourceFileAction(); + + virtual bool hasASTSupport() const { return false; } + +public: + FixItAction(); + ~FixItAction(); +}; + +class GeneratePCHAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool usesCompleteTranslationUnit() { return false; } + + virtual bool hasASTSupport() const { return false; } +}; + +class HTMLPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class InheritanceViewAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class RewriteObjCAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class SyntaxOnlyAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + +public: + virtual bool hasCodeCompletionSupport() const { return true; } +}; + +class BoostConAction : public SyntaxOnlyAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +/** + * \brief Frontend action adaptor that merges ASTs together. + * + * This action takes an existing AST file and "merges" it into the AST + * context, producing a merged context. This action is an action + * adaptor, which forwards most of its calls to another action that + * will consume the merged context. + */ +class ASTMergeAction : public FrontendAction { + /// \brief The action that the merge action adapts. + FrontendAction *AdaptedAction; + + /// \brief The set of AST files to merge. + std::vector<std::string> ASTFiles; + +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + + virtual void ExecuteAction(); + virtual void EndSourceFileAction(); + +public: + ASTMergeAction(FrontendAction *AdaptedAction, + std::string *ASTFiles, unsigned NumASTFiles); + virtual ~ASTMergeAction(); + + virtual bool usesPreprocessorOnly() const; + virtual bool usesCompleteTranslationUnit(); + virtual bool hasPCHSupport() const; + virtual bool hasASTSupport() const; + virtual bool hasCodeCompletionSupport() const; +}; + +//===----------------------------------------------------------------------===// +// Preprocessor Actions +//===----------------------------------------------------------------------===// + +class DumpRawTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class DumpTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class GeneratePTHAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class ParseOnlyAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PreprocessOnlyAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PrintParseAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PrintPreprocessedAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); + + virtual bool hasPCHSupport() const { return true; } +}; + +class RewriteMacrosAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class RewriteTestAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h new file mode 100644 index 0000000..61ad22c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticFrontend.h - Diagnostics for frontend --------*- 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_FRONTENDDIAGNOSTIC_H +#define LLVM_CLANG_FRONTENDDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define FRONTENDSTART +#include "clang/Basic/DiagnosticFrontendKinds.inc" +#undef DIAG + NUM_BUILTIN_FRONTEND_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h new file mode 100644 index 0000000..c43e680 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h @@ -0,0 +1,146 @@ +//===--- FrontendOptions.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H + +#include "clang/Frontend/CommandLineSourceLoc.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace clang { + +namespace frontend { + enum ActionKind { + ASTDump, ///< Parse ASTs and dump them. + ASTPrint, ///< Parse ASTs and print them. + ASTPrintXML, ///< Parse ASTs and print them in XML. + ASTView, ///< Parse ASTs and view them in Graphviz. + BoostCon, ///< BoostCon mode. + DumpRawTokens, ///< Dump out raw tokens. + DumpTokens, ///< Dump out preprocessed tokens. + EmitAssembly, ///< Emit a .s file. + EmitBC, ///< Emit a .bc file. + EmitHTML, ///< Translate input source into HTML. + EmitLLVM, ///< Emit a .ll file. + EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything. + EmitCodeGenOnly, ///< Generate machine code, but don't emit anything. + EmitObj, ///< Emit a .o file. + FixIt, ///< Parse and apply any fixits to the source. + GeneratePCH, ///< Generate pre-compiled header. + GeneratePTH, ///< Generate pre-tokenized header. + InheritanceView, ///< View C++ inheritance for a specified class. + InitOnly, ///< Only execute frontend initialization. + ParseNoop, ///< Parse with noop callbacks. + ParsePrintCallbacks, ///< Parse and print each callback. + ParseSyntaxOnly, ///< Parse and perform semantic analysis. + PluginAction, ///< Run a plugin action, \see ActionName. + PrintDeclContext, ///< Print DeclContext and their Decls. + PrintPreprocessedInput, ///< -E mode. + RewriteMacros, ///< Expand macros but not #includes. + RewriteObjC, ///< ObjC->C Rewriter. + RewriteTest, ///< Rewriter playground + RunAnalysis, ///< Run one or more source code analyses. + RunPreprocessorOnly ///< Just lex, no output. + }; +} + +/// FrontendOptions - Options for controlling the behavior of the frontend. +class FrontendOptions { +public: + 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_AST + }; + + unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code + /// completion results. + unsigned DisableFree : 1; ///< Disable memory freeing on exit. + unsigned RelocatablePCH : 1; ///< When generating PCH files, + /// instruct the PCH writer to create + /// relocatable PCH files. + unsigned ShowHelp : 1; ///< Show the -help text. + unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion + /// results. + unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code + /// completion results. + unsigned ShowStats : 1; ///< Show frontend performance + /// metrics and statistics. + unsigned ShowTimers : 1; ///< Show timers for individual + /// actions. + unsigned ShowVersion : 1; ///< Show the -version text. + + /// The input files and their types. + std::vector<std::pair<InputKind, std::string> > Inputs; + + /// The output file, if any. + std::string OutputFile; + + /// If given, the name for a C++ class to view the inheritance of. + std::string ViewClassInheritance; + + /// If given, the new suffix for fix-it rewritten files. + std::string FixItSuffix; + + /// If given, enable code completion at the provided location. + ParsedSourceLocation CodeCompletionAt; + + /// The frontend action to perform. + frontend::ActionKind ProgramAction; + + /// The name of the action to run when using a plugin action. + std::string ActionName; + + /// The list of plugins to load. + std::vector<std::string> Plugins; + + /// \brief The list of AST files to merge. + std::vector<std::string> ASTMergeFiles; + + /// \brief A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector<std::string> LLVMArgs; + +public: + FrontendOptions() { + DebugCodeCompletionPrinter = 1; + DisableFree = 0; + ProgramAction = frontend::ParseSyntaxOnly; + ActionName = ""; + RelocatablePCH = 0; + ShowHelp = 0; + ShowMacrosInCodeCompletion = 0; + ShowCodePatternsInCodeCompletion = 0; + ShowStats = 0; + ShowTimers = 0; + ShowVersion = 0; + } + + /// getInputKindForExtension - Return the appropriate input kind for a file + /// extension. For example, "c" would return IK_C. + /// + /// \return The input kind for the extension, or IK_None if the extension is + /// not recognized. + static InputKind getInputKindForExtension(llvm::StringRef Extension); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h new file mode 100644 index 0000000..8341492 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h @@ -0,0 +1,23 @@ +//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H +#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/Support/Registry.h" + +namespace clang { + +/// The frontend plugin registry. +typedef llvm::Registry<FrontendAction> FrontendPluginRegistry; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h new file mode 100644 index 0000000..c668245 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h @@ -0,0 +1,95 @@ +//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H +#define LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H + +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { + +namespace frontend { + /// IncludeDirGroup - Identifiers the group a include entry belongs to, which + /// represents its relative positive in the search list. + enum IncludeDirGroup { + Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`. + Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`) + System, ///< Like Angled, but marks system directories. + After ///< Like System, but searched after the system directories. + }; +} + +/// HeaderSearchOptions - Helper class for storing options related to the +/// initialization of the HeaderSearch object. +class HeaderSearchOptions { +public: + struct Entry { + std::string Path; + frontend::IncludeDirGroup Group; + unsigned IsUserSupplied : 1; + unsigned IsFramework : 1; + + Entry(llvm::StringRef _Path, frontend::IncludeDirGroup _Group, + bool _IsUserSupplied, bool _IsFramework) + : Path(_Path), Group(_Group), IsUserSupplied(_IsUserSupplied), + IsFramework(_IsFramework) {} + }; + + /// If non-empty, the directory to use as a "virtual system root" for include + /// paths. + std::string Sysroot; + + /// User specified include entries. + std::vector<Entry> UserEntries; + + /// A (system-path) delimited list of include paths to be added from the + /// environment following the user specified includes (but prior to builtin + /// and standard includes). This is parsed in the same manner as the CPATH + /// environment variable for gcc. + std::string EnvIncPath; + + /// Per-language environmental include paths, see \see EnvIncPath. + std::string CEnvIncPath; + std::string ObjCEnvIncPath; + std::string CXXEnvIncPath; + std::string ObjCXXEnvIncPath; + + /// The directory which holds the compiler resource files (builtin includes, + /// etc.). + std::string ResourceDir; + + /// Include the compiler builtin includes. + unsigned UseBuiltinIncludes : 1; + + /// Include the system standard include search directories. + unsigned UseStandardIncludes : 1; + + /// Include the system standard C++ library include search directories. + unsigned UseStandardCXXIncludes : 1; + + /// Whether header search information should be output as for -v. + unsigned Verbose : 1; + +public: + HeaderSearchOptions(llvm::StringRef _Sysroot = "/") + : Sysroot(_Sysroot), UseBuiltinIncludes(true), + UseStandardIncludes(true), UseStandardCXXIncludes(true), + Verbose(false) {} + + /// AddPath - Add the \arg Path path to the specified \arg Group list. + void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, + bool IsUserSupplied, bool IsFramework) { + UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework)); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h new file mode 100644 index 0000000..441d34f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h @@ -0,0 +1,83 @@ +//===--- LangStandard.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H +#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H + +#include "llvm/ADT/StringRef.h" + +namespace clang { + +namespace frontend { + +enum LangFeatures { + BCPLComment = (1 << 0), + C99 = (1 << 1), + CPlusPlus = (1 << 2), + CPlusPlus0x = (1 << 3), + Digraphs = (1 << 4), + GNUMode = (1 << 5), + HexFloat = (1 << 6), + ImplicitInt = (1 << 7) +}; + +} + +/// LangStandard - Information about the properties of a particular language +/// standard. +struct LangStandard { + enum Kind { +#define LANGSTANDARD(id, name, desc, features) \ + lang_##id, +#include "clang/Frontend/LangStandards.def" + lang_unspecified + }; + + const char *ShortName; + const char *Description; + unsigned Flags; + +public: + /// getName - Get the name of this standard. + const char *getName() const { return ShortName; } + + /// getDescription - Get the description of this standard. + const char *getDescription() const { return Description; } + + /// hasBCPLComments - Language supports '//' comments. + bool hasBCPLComments() const { return Flags & frontend::BCPLComment; } + + /// isC99 - Language is a superset of C99. + bool isC99() const { return Flags & frontend::C99; } + + /// isCPlusPlus - Language is a C++ variant. + bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } + + /// isCPlusPlus0x - Language is a C++0x variant. + bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; } + + /// hasDigraphs - Language supports digraphs. + bool hasDigraphs() const { return Flags & frontend::Digraphs; } + + /// isGNUMode - Language includes GNU extensions. + bool isGNUMode() const { return Flags & frontend::GNUMode; } + + /// hasHexFloats - Language supports hexadecimal float constants. + bool hasHexFloats() const { return Flags & frontend::HexFloat; } + + /// hasImplicitInt - Language allows variables to be typed as int implicitly. + bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; } + + static const LangStandard &getLangStandardForKind(Kind K); + static const LangStandard *getLangStandardForName(llvm::StringRef Name); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def new file mode 100644 index 0000000..52aa463 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def @@ -0,0 +1,83 @@ +//===-- LangStandards.def - Language Standard Data --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LANGSTANDARD +#error "LANGSTANDARD must be defined before including this file" +#endif + +/// LANGSTANDARD(IDENT, NAME, DESC, FEATURES) +/// +/// \param IDENT - The name of the standard as a C++ identifier. +/// \param NAME - The name of the standard. +/// \param DESC - A short description of the standard. +/// \param FEATURES - The standard features as flags, these are enums from the +/// clang::frontend namespace, which is assumed to be be available. + +// C89-ish modes. +LANGSTANDARD(c89, "c89", + "ISO C 1990", + ImplicitInt) +LANGSTANDARD(c90, "c90", + "ISO C 1990", + ImplicitInt) +LANGSTANDARD(iso9899_1990, "iso9899:1990", + "ISO C 1990", + ImplicitInt) + +LANGSTANDARD(c94, "iso9899:199409", + "ISO C 1990 with amendment 1", + Digraphs | ImplicitInt) + +LANGSTANDARD(gnu89, "gnu89", + "ISO C 1990 with GNU extensions", + BCPLComment | Digraphs | GNUMode | ImplicitInt) + +// C99-ish modes +LANGSTANDARD(c99, "c99", + "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(c9x, "c9x", + "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(iso9899_1999, + "iso9899:1999", "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(iso9899_199x, + "iso9899:199x", "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) + +LANGSTANDARD(gnu99, "gnu99", + "ISO C 1999 with GNU extensions", + BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs) +LANGSTANDARD(gnu9x, "gnu9x", + "ISO C 1999 with GNU extensions", + BCPLComment | C99 | Digraphs | GNUMode | HexFloat) + +// C++ modes +LANGSTANDARD(cxx98, "c++98", + "ISO C++ 1998 with amendments", + BCPLComment | CPlusPlus | Digraphs) +LANGSTANDARD(gnucxx98, "gnu++98", + "ISO C++ 1998 with " "amendments and GNU extensions", + BCPLComment | CPlusPlus | Digraphs | GNUMode) + +LANGSTANDARD(cxx0x, "c++0x", + "Upcoming ISO C++ 200x with amendments", + BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs) +LANGSTANDARD(gnucxx0x, "gnu++0x", + "Upcoming ISO C++ 200x with amendments and GNU extensions", + BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + +// OpenCL + +LANGSTANDARD(opencl, "cl", + "OpenCL 1.0", + BCPLComment | C99 | Digraphs | HexFloat) + +#undef LANGSTANDARD diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHBitCodes.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHBitCodes.h new file mode 100644 index 0000000..2493cfd --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHBitCodes.h @@ -0,0 +1,783 @@ +//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines Bitcode enum values for Clang precompiled header files. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H +#define LLVM_CLANG_FRONTEND_PCHBITCODES_H + +#include "llvm/Bitcode/BitCodes.h" +#include "llvm/System/DataTypes.h" + +namespace clang { + namespace pch { + /// \brief PCH major version number supported by this version of + /// Clang. + /// + /// Whenever the PCH format changes in a way that makes it + /// incompatible with previous versions (such that a reader + /// designed for the previous version could not support reading + /// the new version), this number should be increased. + /// + /// Version 3 of PCH files also requires that the version control branch and + /// revision match exactly, since there is no backward compatibility of + /// PCH files at this time. + const unsigned VERSION_MAJOR = 3; + + /// \brief PCH minor version number supported by this version of + /// Clang. + /// + /// Whenever the PCH format changes in a way that is still + /// compatible with previous versions (such that a reader designed + /// for the previous version could still support reading the new + /// version by ignoring new kinds of subblocks), this number + /// should be increased. + const unsigned VERSION_MINOR = 0; + + /// \brief An ID number that refers to a declaration in a PCH file. + /// + /// The ID numbers of types are consecutive (in order of + /// discovery) and start at 2. 0 is reserved for NULL, and 1 is + /// reserved for the translation unit declaration. + typedef uint32_t DeclID; + + /// \brief An ID number that refers to a type in a PCH file. + /// + /// The ID of a type is partitioned into two parts: the lower + /// three bits are used to store the const/volatile/restrict + /// qualifiers (as with QualType) and the upper bits provide a + /// type index. The type index values are partitioned into two + /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type + /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a + /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are + /// other types that have serialized representations. + typedef uint32_t TypeID; + + /// \brief An ID number that refers to an identifier in a PCH + /// file. + typedef uint32_t IdentID; + + typedef uint32_t SelectorID; + + /// \brief Describes the various kinds of blocks that occur within + /// a PCH file. + enum BlockIDs { + /// \brief The PCH block, which acts as a container around the + /// full PCH block. + PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// \brief The block containing information about the source + /// manager. + SOURCE_MANAGER_BLOCK_ID, + + /// \brief The block containing information about the + /// preprocessor. + PREPROCESSOR_BLOCK_ID, + + /// \brief The block containing the definitions of all of the + /// types and decls used within the PCH file. + DECLTYPES_BLOCK_ID + }; + + /// \brief Record types that occur within the PCH block itself. + enum PCHRecordTypes { + /// \brief Record code for the offsets of each type. + /// + /// The TYPE_OFFSET constant describes the record that occurs + /// within the PCH block. The record itself is an array of offsets that + /// point into the declarations and types block (identified by + /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID + /// of a type. For a given type ID @c T, the lower three bits of + /// @c T are its qualifiers (const, volatile, restrict), as in + /// the QualType class. The upper bits, after being shifted and + /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the + /// TYPE_OFFSET block to determine the offset of that type's + /// corresponding record within the DECLTYPES_BLOCK_ID block. + TYPE_OFFSET = 1, + + /// \brief Record code for the offsets of each decl. + /// + /// The DECL_OFFSET constant describes the record that occurs + /// within the block identified by DECL_OFFSETS_BLOCK_ID within + /// the PCH block. The record itself is an array of offsets that + /// point into the declarations and types block (identified by + /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this + /// record, after subtracting one to account for the use of + /// declaration ID 0 for a NULL declaration pointer. Index 0 is + /// reserved for the translation unit declaration. + DECL_OFFSET = 2, + + /// \brief Record code for the language options table. + /// + /// The record with this code contains the contents of the + /// LangOptions structure. We serialize the entire contents of + /// the structure, and let the reader decide which options are + /// actually important to check. + LANGUAGE_OPTIONS = 3, + + /// \brief PCH metadata, including the PCH file version number + /// and the target triple used to build the PCH file. + METADATA = 4, + + /// \brief Record code for the table of offsets of each + /// identifier ID. + /// + /// The offset table contains offsets into the blob stored in + /// the IDENTIFIER_TABLE record. Each offset points to the + /// NULL-terminated string that corresponds to that identifier. + IDENTIFIER_OFFSET = 5, + + /// \brief Record code for the identifier table. + /// + /// The identifier table is a simple blob that contains + /// NULL-terminated strings for all of the identifiers + /// referenced by the PCH file. The IDENTIFIER_OFFSET table + /// contains the mapping from identifier IDs to the characters + /// in this blob. Note that the starting offsets of all of the + /// identifiers are odd, so that, when the identifier offset + /// table is loaded in, we can use the low bit to distinguish + /// between offsets (for unresolved identifier IDs) and + /// IdentifierInfo pointers (for already-resolved identifier + /// IDs). + IDENTIFIER_TABLE = 6, + + /// \brief Record code for the array of external definitions. + /// + /// The PCH file contains a list of all of the unnamed external + /// definitions present within the parsed headers, stored as an + /// array of declaration IDs. These external definitions will be + /// reported to the AST consumer after the PCH file has been + /// read, since their presence can affect the semantics of the + /// program (e.g., for code generation). + EXTERNAL_DEFINITIONS = 7, + + /// \brief Record code for the set of non-builtin, special + /// types. + /// + /// This record contains the type IDs for the various type nodes + /// that are constructed during semantic analysis (e.g., + /// __builtin_va_list). The SPECIAL_TYPE_* constants provide + /// offsets into this record. + SPECIAL_TYPES = 8, + + /// \brief Record code for the extra statistics we gather while + /// generating a PCH file. + STATISTICS = 9, + + /// \brief Record code for the array of tentative definitions. + TENTATIVE_DEFINITIONS = 10, + + /// \brief Record code for the array of locally-scoped external + /// declarations. + LOCALLY_SCOPED_EXTERNAL_DECLS = 11, + + /// \brief Record code for the table of offsets into the + /// Objective-C method pool. + SELECTOR_OFFSETS = 12, + + /// \brief Record code for the Objective-C method pool, + METHOD_POOL = 13, + + /// \brief The value of the next __COUNTER__ to dispense. + /// [PP_COUNTER_VALUE, Val] + PP_COUNTER_VALUE = 14, + + /// \brief Record code for the table of offsets into the block + /// of source-location information. + SOURCE_LOCATION_OFFSETS = 15, + + /// \brief Record code for the set of source location entries + /// that need to be preloaded by the PCH reader. + /// + /// This set contains the source location entry for the + /// predefines buffer and for any file entries that need to be + /// preloaded. + SOURCE_LOCATION_PRELOADS = 16, + + /// \brief Record code for the stat() cache. + STAT_CACHE = 17, + + /// \brief Record code for the set of ext_vector type names. + EXT_VECTOR_DECLS = 18, + + /// \brief Record code for the original file that was used to + /// generate the precompiled header. + ORIGINAL_FILE_NAME = 19, + + /// Record #20 intentionally left blank. + + /// \brief Record code for the version control branch and revision + /// information of the compiler used to build this PCH file. + VERSION_CONTROL_BRANCH_REVISION = 21, + + /// \brief Record code for the array of unused static functions. + UNUSED_STATIC_FUNCS = 22, + + /// \brief Record code for the table of offsets to macro definition + /// entries in the preprocessing record. + MACRO_DEFINITION_OFFSETS = 23 + }; + + /// \brief Record types used within a source manager block. + enum SourceManagerRecordTypes { + /// \brief Describes a source location entry (SLocEntry) for a + /// file. + SM_SLOC_FILE_ENTRY = 1, + /// \brief Describes a source location entry (SLocEntry) for a + /// buffer. + 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_BLOB = 3, + /// \brief Describes a source location entry (SLocEntry) for a + /// macro instantiation. + SM_SLOC_INSTANTIATION_ENTRY = 4, + /// \brief Describes the SourceManager's line table, with + /// information about #line directives. + SM_LINE_TABLE = 5 + }; + + /// \brief Record types used within a preprocessor block. + enum PreprocessorRecordTypes { + // The macros in the PP section are a PP_MACRO_* instance followed by a + // list of PP_TOKEN instances for each token in the definition. + + /// \brief An object-like macro definition. + /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed] + PP_MACRO_OBJECT_LIKE = 1, + + /// \brief A function-like macro definition. + /// [PP_MACRO_FUNCTION_LIKE, <ObjectLikeStuff>, IsC99Varargs, IsGNUVarars, + /// NumArgs, ArgIdentInfoID* ] + PP_MACRO_FUNCTION_LIKE = 2, + + /// \brief Describes one token. + /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] + PP_TOKEN = 3, + + /// \brief Describes a macro instantiation within the preprocessing + /// record. + PP_MACRO_INSTANTIATION = 4, + + /// \brief Describes a macro definition within the preprocessing record. + PP_MACRO_DEFINITION = 5 + }; + + /// \defgroup PCHAST Precompiled header AST constants + /// + /// The constants in this group describe various components of the + /// abstract syntax tree within a precompiled header. + /// + /// @{ + + /// \brief Predefined type IDs. + /// + /// These type IDs correspond to predefined types in the AST + /// context, such as built-in types (int) and special place-holder + /// types (the <overload> and <dependent> type markers). Such + /// types are never actually serialized, since they will be built + /// by the AST context when it is created. + enum PredefinedTypeIDs { + /// \brief The NULL type. + PREDEF_TYPE_NULL_ID = 0, + /// \brief The void type. + PREDEF_TYPE_VOID_ID = 1, + /// \brief The 'bool' or '_Bool' type. + PREDEF_TYPE_BOOL_ID = 2, + /// \brief The 'char' type, when it is unsigned. + PREDEF_TYPE_CHAR_U_ID = 3, + /// \brief The 'unsigned char' type. + PREDEF_TYPE_UCHAR_ID = 4, + /// \brief The 'unsigned short' type. + PREDEF_TYPE_USHORT_ID = 5, + /// \brief The 'unsigned int' type. + PREDEF_TYPE_UINT_ID = 6, + /// \brief The 'unsigned long' type. + PREDEF_TYPE_ULONG_ID = 7, + /// \brief The 'unsigned long long' type. + PREDEF_TYPE_ULONGLONG_ID = 8, + /// \brief The 'char' type, when it is signed. + PREDEF_TYPE_CHAR_S_ID = 9, + /// \brief The 'signed char' type. + PREDEF_TYPE_SCHAR_ID = 10, + /// \brief The C++ 'wchar_t' type. + PREDEF_TYPE_WCHAR_ID = 11, + /// \brief The (signed) 'short' type. + PREDEF_TYPE_SHORT_ID = 12, + /// \brief The (signed) 'int' type. + PREDEF_TYPE_INT_ID = 13, + /// \brief The (signed) 'long' type. + PREDEF_TYPE_LONG_ID = 14, + /// \brief The (signed) 'long long' type. + PREDEF_TYPE_LONGLONG_ID = 15, + /// \brief The 'float' type. + PREDEF_TYPE_FLOAT_ID = 16, + /// \brief The 'double' type. + PREDEF_TYPE_DOUBLE_ID = 17, + /// \brief The 'long double' type. + PREDEF_TYPE_LONGDOUBLE_ID = 18, + /// \brief The placeholder type for overloaded function sets. + PREDEF_TYPE_OVERLOAD_ID = 19, + /// \brief The placeholder type for dependent types. + PREDEF_TYPE_DEPENDENT_ID = 20, + /// \brief The '__uint128_t' type. + PREDEF_TYPE_UINT128_ID = 21, + /// \brief The '__int128_t' type. + PREDEF_TYPE_INT128_ID = 22, + /// \brief The type of 'nullptr'. + PREDEF_TYPE_NULLPTR_ID = 23, + /// \brief The C++ 'char16_t' type. + PREDEF_TYPE_CHAR16_ID = 24, + /// \brief The C++ 'char32_t' type. + PREDEF_TYPE_CHAR32_ID = 25, + /// \brief The ObjC 'id' type. + PREDEF_TYPE_OBJC_ID = 26, + /// \brief The ObjC 'Class' type. + PREDEF_TYPE_OBJC_CLASS = 27, + /// \brief The ObjC 'SEL' type. + PREDEF_TYPE_OBJC_SEL = 28 + }; + + /// \brief The number of predefined type IDs that are reserved for + /// the PREDEF_TYPE_* constants. + /// + /// Type IDs for non-predefined types will start at + /// NUM_PREDEF_TYPE_IDs. + const unsigned NUM_PREDEF_TYPE_IDS = 100; + + /// \brief Record codes for each kind of type. + /// + /// These constants describe the type records that can occur within a + /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each + /// constant describes a record for a specific type class in the + /// AST. + enum TypeCode { + /// \brief An ExtQualType record. + TYPE_EXT_QUAL = 1, + /// \brief A ComplexType record. + TYPE_COMPLEX = 3, + /// \brief A PointerType record. + TYPE_POINTER = 4, + /// \brief A BlockPointerType record. + TYPE_BLOCK_POINTER = 5, + /// \brief An LValueReferenceType record. + TYPE_LVALUE_REFERENCE = 6, + /// \brief An RValueReferenceType record. + TYPE_RVALUE_REFERENCE = 7, + /// \brief A MemberPointerType record. + TYPE_MEMBER_POINTER = 8, + /// \brief A ConstantArrayType record. + TYPE_CONSTANT_ARRAY = 9, + /// \brief An IncompleteArrayType record. + TYPE_INCOMPLETE_ARRAY = 10, + /// \brief A VariableArrayType record. + TYPE_VARIABLE_ARRAY = 11, + /// \brief A VectorType record. + TYPE_VECTOR = 12, + /// \brief An ExtVectorType record. + TYPE_EXT_VECTOR = 13, + /// \brief A FunctionNoProtoType record. + TYPE_FUNCTION_NO_PROTO = 14, + /// \brief A FunctionProtoType record. + TYPE_FUNCTION_PROTO = 15, + /// \brief A TypedefType record. + TYPE_TYPEDEF = 16, + /// \brief A TypeOfExprType record. + TYPE_TYPEOF_EXPR = 17, + /// \brief A TypeOfType record. + TYPE_TYPEOF = 18, + /// \brief A RecordType record. + TYPE_RECORD = 19, + /// \brief An EnumType record. + TYPE_ENUM = 20, + /// \brief An ObjCInterfaceType record. + TYPE_OBJC_INTERFACE = 21, + /// \brief An ObjCObjectPointerType record. + TYPE_OBJC_OBJECT_POINTER = 22, + /// \brief a DecltypeType record. + TYPE_DECLTYPE = 23, + /// \brief An ElaboratedType record. + TYPE_ELABORATED = 24, + /// \brief A SubstTemplateTypeParmType record. + TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, + /// \brief An UnresolvedUsingType record. + TYPE_UNRESOLVED_USING = 26, + /// \brief An InjectedClassNameType record. + TYPE_INJECTED_CLASS_NAME = 27, + /// \brief An ObjCObjectType record. + TYPE_OBJC_OBJECT = 28 + }; + + /// \brief The type IDs for special types constructed by semantic + /// analysis. + /// + /// The constants in this enumeration are indices into the + /// SPECIAL_TYPES record. + enum SpecialTypeIDs { + /// \brief __builtin_va_list + SPECIAL_TYPE_BUILTIN_VA_LIST = 0, + /// \brief Objective-C "id" type + SPECIAL_TYPE_OBJC_ID = 1, + /// \brief Objective-C selector type + SPECIAL_TYPE_OBJC_SELECTOR = 2, + /// \brief Objective-C Protocol type + SPECIAL_TYPE_OBJC_PROTOCOL = 3, + /// \brief Objective-C Class type + SPECIAL_TYPE_OBJC_CLASS = 4, + /// \brief CFConstantString type + SPECIAL_TYPE_CF_CONSTANT_STRING = 5, + /// \brief Objective-C fast enumeration state type + SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6, + /// \brief C FILE typedef type + SPECIAL_TYPE_FILE = 7, + /// \brief C jmp_buf typedef type + SPECIAL_TYPE_jmp_buf = 8, + /// \brief C sigjmp_buf typedef type + SPECIAL_TYPE_sigjmp_buf = 9, + /// \brief Objective-C "id" redefinition type + SPECIAL_TYPE_OBJC_ID_REDEFINITION = 10, + /// \brief Objective-C "Class" redefinition type + SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11, + /// \brief Block descriptor type for Blocks CodeGen + SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12, + /// \brief Block extedned descriptor type for Blocks CodeGen + SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13, + /// \brief Objective-C "SEL" redefinition type + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14, + /// \brief NSConstantString type + SPECIAL_TYPE_NS_CONSTANT_STRING = 15 + }; + + /// \brief Record codes for each kind of declaration. + /// + /// These constants describe the declaration records that can occur within + /// a declarations block (identified by DECLS_BLOCK_ID). Each + /// constant describes a record for a specific declaration class + /// in the AST. + enum DeclCode { + /// \brief Attributes attached to a declaration. + DECL_ATTR = 50, + /// \brief A TranslationUnitDecl record. + DECL_TRANSLATION_UNIT, + /// \brief A TypedefDecl record. + DECL_TYPEDEF, + /// \brief An EnumDecl record. + DECL_ENUM, + /// \brief A RecordDecl record. + DECL_RECORD, + /// \brief An EnumConstantDecl record. + DECL_ENUM_CONSTANT, + /// \brief A FunctionDecl record. + DECL_FUNCTION, + /// \brief A ObjCMethodDecl record. + DECL_OBJC_METHOD, + /// \brief A ObjCInterfaceDecl record. + DECL_OBJC_INTERFACE, + /// \brief A ObjCProtocolDecl record. + DECL_OBJC_PROTOCOL, + /// \brief A ObjCIvarDecl record. + 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. + DECL_OBJC_CATEGORY_IMPL, + /// \brief A ObjCImplementationDecl record. + DECL_OBJC_IMPLEMENTATION, + /// \brief A ObjCCompatibleAliasDecl record. + DECL_OBJC_COMPATIBLE_ALIAS, + /// \brief A ObjCPropertyDecl record. + DECL_OBJC_PROPERTY, + /// \brief A ObjCPropertyImplDecl record. + DECL_OBJC_PROPERTY_IMPL, + /// \brief A FieldDecl record. + DECL_FIELD, + /// \brief A VarDecl record. + DECL_VAR, + /// \brief An ImplicitParamDecl record. + DECL_IMPLICIT_PARAM, + /// \brief A ParmVarDecl record. + DECL_PARM_VAR, + /// \brief A FileScopeAsmDecl record. + DECL_FILE_SCOPE_ASM, + /// \brief A BlockDecl record. + DECL_BLOCK, + /// \brief A record that stores the set of declarations that are + /// lexically stored within a given DeclContext. + /// + /// The record itself is an array of declaration IDs, in the + /// order in which those declarations were added to the + /// declaration context. This data is used when iterating over + /// the contents of a DeclContext, e.g., via + /// DeclContext::decls_begin()/DeclContext::decls_end(). + DECL_CONTEXT_LEXICAL, + /// \brief A record that stores the set of declarations that are + /// visible from a given DeclContext. + /// + /// The record itself stores a set of mappings, each of which + /// associates a declaration name with one or more declaration + /// IDs. This data is used when performing qualified name lookup + /// into a DeclContext via DeclContext::lookup. + DECL_CONTEXT_VISIBLE, + /// \brief A NamespaceDecl rcord. + DECL_NAMESPACE, + /// \brief A NamespaceAliasDecl record. + DECL_NAMESPACE_ALIAS, + /// \brief A UsingDecl record. + DECL_USING, + /// \brief A UsingShadowDecl record. + DECL_USING_SHADOW, + /// \brief A UsingDirecitveDecl record. + DECL_USING_DIRECTIVE, + /// \brief An UnresolvedUsingValueDecl record. + DECL_UNRESOLVED_USING_VALUE, + /// \brief An UnresolvedUsingTypenameDecl record. + DECL_UNRESOLVED_USING_TYPENAME, + /// \brief A LinkageSpecDecl record. + DECL_LINKAGE_SPEC, + /// \brief A CXXRecordDecl record. + DECL_CXX_RECORD, + /// \brief A CXXMethodDecl record. + DECL_CXX_METHOD, + /// \brief A CXXConstructorDecl record. + DECL_CXX_CONSTRUCTOR, + /// \brief A CXXDestructorDecl record. + DECL_CXX_DESTRUCTOR, + /// \brief A CXXConversionDecl record. + DECL_CXX_CONVERSION, + + // FIXME: Implement serialization for these decl types. This just + // allocates the order in which + DECL_FRIEND, + DECL_FRIEND_TEMPLATE, + DECL_TEMPLATE, + DECL_CLASS_TEMPLATE, + DECL_CLASS_TEMPLATE_SPECIALIZATION, + DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, + DECL_FUNCTION_TEMPLATE, + DECL_TEMPLATE_TYPE_PARM, + DECL_NON_TYPE_TEMPLATE_PARM, + DECL_TEMPLATE_TEMPLATE_PARM, + DECL_STATIC_ASSERT + }; + + /// \brief Record codes for each kind of statement or expression. + /// + /// These constants describe the records that describe statements + /// or expressions. These records occur within type and declarations + /// block, so they begin with record values of 100. Each constant + /// describes a record for a specific statement or expression class in the + /// AST. + enum StmtCode { + /// \brief A marker record that indicates that we are at the end + /// of an expression. + STMT_STOP = 100, + /// \brief A NULL expression. + STMT_NULL_PTR, + /// \brief A NullStmt record. + STMT_NULL, + /// \brief A CompoundStmt record. + STMT_COMPOUND, + /// \brief A CaseStmt record. + STMT_CASE, + /// \brief A DefaultStmt record. + STMT_DEFAULT, + /// \brief A LabelStmt record. + STMT_LABEL, + /// \brief An IfStmt record. + STMT_IF, + /// \brief A SwitchStmt record. + STMT_SWITCH, + /// \brief A WhileStmt record. + STMT_WHILE, + /// \brief A DoStmt record. + STMT_DO, + /// \brief A ForStmt record. + STMT_FOR, + /// \brief A GotoStmt record. + STMT_GOTO, + /// \brief An IndirectGotoStmt record. + STMT_INDIRECT_GOTO, + /// \brief A ContinueStmt record. + STMT_CONTINUE, + /// \brief A BreakStmt record. + STMT_BREAK, + /// \brief A ReturnStmt record. + STMT_RETURN, + /// \brief A DeclStmt record. + STMT_DECL, + /// \brief An AsmStmt record. + STMT_ASM, + /// \brief A PredefinedExpr record. + EXPR_PREDEFINED, + /// \brief A DeclRefExpr record. + EXPR_DECL_REF, + /// \brief An IntegerLiteral record. + EXPR_INTEGER_LITERAL, + /// \brief A FloatingLiteral record. + EXPR_FLOATING_LITERAL, + /// \brief An ImaginaryLiteral record. + EXPR_IMAGINARY_LITERAL, + /// \brief A StringLiteral record. + EXPR_STRING_LITERAL, + /// \brief A CharacterLiteral record. + EXPR_CHARACTER_LITERAL, + /// \brief A ParenExpr record. + EXPR_PAREN, + /// \brief A UnaryOperator record. + EXPR_UNARY_OPERATOR, + /// \brief An OffsetOfExpr record. + EXPR_OFFSETOF, + /// \brief A SizefAlignOfExpr record. + EXPR_SIZEOF_ALIGN_OF, + /// \brief An ArraySubscriptExpr record. + EXPR_ARRAY_SUBSCRIPT, + /// \brief A CallExpr record. + EXPR_CALL, + /// \brief A MemberExpr record. + EXPR_MEMBER, + /// \brief A BinaryOperator record. + EXPR_BINARY_OPERATOR, + /// \brief A CompoundAssignOperator record. + EXPR_COMPOUND_ASSIGN_OPERATOR, + /// \brief A ConditionOperator record. + EXPR_CONDITIONAL_OPERATOR, + /// \brief An ImplicitCastExpr record. + EXPR_IMPLICIT_CAST, + /// \brief A CStyleCastExpr record. + EXPR_CSTYLE_CAST, + /// \brief A CompoundLiteralExpr record. + EXPR_COMPOUND_LITERAL, + /// \brief An ExtVectorElementExpr record. + EXPR_EXT_VECTOR_ELEMENT, + /// \brief An InitListExpr record. + EXPR_INIT_LIST, + /// \brief A DesignatedInitExpr record. + EXPR_DESIGNATED_INIT, + /// \brief An ImplicitValueInitExpr record. + EXPR_IMPLICIT_VALUE_INIT, + /// \brief A VAArgExpr record. + EXPR_VA_ARG, + /// \brief An AddrLabelExpr record. + EXPR_ADDR_LABEL, + /// \brief A StmtExpr record. + EXPR_STMT, + /// \brief A TypesCompatibleExpr record. + EXPR_TYPES_COMPATIBLE, + /// \brief A ChooseExpr record. + EXPR_CHOOSE, + /// \brief A GNUNullExpr record. + EXPR_GNU_NULL, + /// \brief A ShuffleVectorExpr record. + EXPR_SHUFFLE_VECTOR, + /// \brief BlockExpr + EXPR_BLOCK, + /// \brief A BlockDeclRef record. + EXPR_BLOCK_DECL_REF, + + // Objective-C + + /// \brief An ObjCStringLiteral record. + EXPR_OBJC_STRING_LITERAL, + /// \brief An ObjCEncodeExpr record. + EXPR_OBJC_ENCODE, + /// \brief An ObjCSelectorExpr record. + EXPR_OBJC_SELECTOR_EXPR, + /// \brief An ObjCProtocolExpr record. + EXPR_OBJC_PROTOCOL_EXPR, + /// \brief An ObjCIvarRefExpr record. + EXPR_OBJC_IVAR_REF_EXPR, + /// \brief An ObjCPropertyRefExpr record. + EXPR_OBJC_PROPERTY_REF_EXPR, + /// \brief An ObjCImplicitSetterGetterRefExpr record. + EXPR_OBJC_KVC_REF_EXPR, + /// \brief An ObjCMessageExpr record. + EXPR_OBJC_MESSAGE_EXPR, + /// \brief An ObjCSuperExpr record. + EXPR_OBJC_SUPER_EXPR, + /// \brief An ObjCIsa Expr record. + EXPR_OBJC_ISA, + + /// \brief An ObjCForCollectionStmt record. + STMT_OBJC_FOR_COLLECTION, + /// \brief An ObjCAtCatchStmt record. + STMT_OBJC_CATCH, + /// \brief An ObjCAtFinallyStmt record. + STMT_OBJC_FINALLY, + /// \brief An ObjCAtTryStmt record. + STMT_OBJC_AT_TRY, + /// \brief An ObjCAtSynchronizedStmt record. + STMT_OBJC_AT_SYNCHRONIZED, + /// \brief An ObjCAtThrowStmt record. + STMT_OBJC_AT_THROW, + + // C++ + + /// \brief A CXXOperatorCallExpr record. + EXPR_CXX_OPERATOR_CALL, + /// \brief A CXXMemberCallExpr record. + EXPR_CXX_MEMBER_CALL, + /// \brief A CXXConstructExpr record. + EXPR_CXX_CONSTRUCT, + // \brief A CXXStaticCastExpr record. + EXPR_CXX_STATIC_CAST, + // \brief A CXXDynamicCastExpr record. + EXPR_CXX_DYNAMIC_CAST, + // \brief A CXXReinterpretCastExpr record. + EXPR_CXX_REINTERPRET_CAST, + // \brief A CXXConstCastExpr record. + EXPR_CXX_CONST_CAST, + // \brief A CXXFunctionalCastExpr record. + EXPR_CXX_FUNCTIONAL_CAST, + // \brief A CXXBoolLiteralExpr record. + EXPR_CXX_BOOL_LITERAL, + EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr + EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr). + EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type). + EXPR_CXX_THIS, // CXXThisExpr + EXPR_CXX_THROW, // CXXThrowExpr + EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr + EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr + // + EXPR_CXX_ZERO_INIT_VALUE, // CXXZeroInitValueExpr + EXPR_CXX_NEW, // CXXNewExpr + + EXPR_CXX_EXPR_WITH_TEMPORARIES // CXXExprWithTemporaries + }; + + /// \brief The kinds of designators that can occur in a + /// DesignatedInitExpr. + enum DesignatorTypes { + /// \brief Field designator where only the field name is known. + DESIG_FIELD_NAME = 0, + /// \brief Field designator where the field has been resolved to + /// a declaration. + DESIG_FIELD_DECL = 1, + /// \brief Array designator. + DESIG_ARRAY = 2, + /// \brief GNU array range designator. + DESIG_ARRAY_RANGE = 3 + }; + + /// @} + } +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHReader.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHReader.h new file mode 100644 index 0000000..e144738 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHReader.h @@ -0,0 +1,827 @@ +//===--- PCHReader.h - Precompiled Headers Reader ---------------*- 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 PCHReader class, which reads a precompiled header. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H +#define LLVM_CLANG_FRONTEND_PCH_READER_H + +#include "clang/Frontend/PCHBitCodes.h" +#include "clang/AST/DeclarationName.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Type.h" +#include "clang/AST/TemplateBase.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/System/DataTypes.h" +#include <deque> +#include <map> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class AddrLabelExpr; +class ASTConsumer; +class ASTContext; +class Attr; +class Decl; +class DeclContext; +class NestedNameSpecifier; +class CXXBaseSpecifier; +class CXXBaseOrMemberInitializer; +class GotoStmt; +class LabelStmt; +class MacroDefinition; +class NamedDecl; +class Preprocessor; +class Sema; +class SwitchCase; +class PCHReader; +struct HeaderFileInfo; + +/// \brief Abstract interface for callback invocations by the PCHReader. +/// +/// While reading a PCH file, the PCHReader will call the methods of the +/// listener to pass on specific information. Some of the listener methods can +/// return true to indicate to the PCHReader that the information (and +/// consequently the PCH file) is invalid. +class PCHReaderListener { +public: + virtual ~PCHReaderListener(); + + /// \brief Receives the language options. + /// + /// \returns true to indicate the options are invalid or false otherwise. + virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { + return false; + } + + /// \brief Receives the target triple. + /// + /// \returns true to indicate the target triple is invalid or false otherwise. + virtual bool ReadTargetTriple(llvm::StringRef Triple) { + return false; + } + + /// \brief Receives the contents of the predefines buffer. + /// + /// \param PCHPredef The start of the predefines buffer in the PCH + /// file. + /// + /// \param PCHBufferID The FileID for the PCH predefines buffer. + /// + /// \param OriginalFileName The original file name for the PCH, which will + /// appear as an entry in the predefines buffer. + /// + /// \param SuggestedPredefines If necessary, additional definitions are added + /// here. + /// + /// \returns true to indicate the predefines are invalid or false otherwise. + virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, + FileID PCHBufferID, + llvm::StringRef OriginalFileName, + std::string &SuggestedPredefines) { + return false; + } + + /// \brief Receives a HeaderFileInfo entry. + virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {} + + /// \brief Receives __COUNTER__ value. + virtual void ReadCounter(unsigned Value) {} +}; + +/// \brief PCHReaderListener implementation to validate the information of +/// the PCH file against an initialized Preprocessor. +class PCHValidator : public PCHReaderListener { + Preprocessor &PP; + PCHReader &Reader; + + unsigned NumHeaderInfos; + +public: + PCHValidator(Preprocessor &PP, PCHReader &Reader) + : PP(PP), Reader(Reader), NumHeaderInfos(0) {} + + virtual bool ReadLanguageOptions(const LangOptions &LangOpts); + virtual bool ReadTargetTriple(llvm::StringRef Triple); + virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, + FileID PCHBufferID, + llvm::StringRef OriginalFileName, + std::string &SuggestedPredefines); + virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID); + virtual void ReadCounter(unsigned Value); + +private: + void Error(const char *Msg); +}; + +/// \brief Reads a precompiled head containing the contents of a +/// translation unit. +/// +/// The PCHReader class reads a bitstream (produced by the PCHWriter +/// class) containing the serialized representation of a given +/// abstract syntax tree and its supporting data structures. An +/// instance of the PCHReader can be attached to an ASTContext object, +/// which will provide access to the contents of the PCH file. +/// +/// The PCH reader provides lazy de-serialization of declarations, as +/// required when traversing the AST. Only those AST nodes that are +/// actually required will be de-serialized. +class PCHReader + : public ExternalPreprocessorSource, + public ExternalPreprocessingRecordSource, + public ExternalSemaSource, + public IdentifierInfoLookup, + public ExternalIdentifierLookup, + public ExternalSLocEntrySource { +public: + enum PCHReadResult { Success, Failure, IgnorePCH }; + friend class PCHValidator; +private: + /// \ brief The receiver of some callbacks invoked by PCHReader. + llvm::OwningPtr<PCHReaderListener> Listener; + + SourceManager &SourceMgr; + FileManager &FileMgr; + Diagnostic &Diags; + + /// \brief The semantic analysis object that will be processing the + /// PCH file and the translation unit that uses it. + Sema *SemaObj; + + /// \brief The preprocessor that will be loading the source file. + Preprocessor *PP; + + /// \brief The AST context into which we'll read the PCH file. + ASTContext *Context; + + /// \brief The PCH stat cache installed by this PCHReader, if any. + /// + /// The dynamic type of this stat cache is always PCHStatCache + void *StatCache; + + /// \brief The AST consumer. + ASTConsumer *Consumer; + + /// \brief The bitstream reader from which we'll read the PCH file. + llvm::BitstreamReader StreamFile; + llvm::BitstreamCursor Stream; + + /// \brief The cursor to the start of the preprocessor block, which stores + /// all of the macro definitions. + llvm::BitstreamCursor MacroCursor; + + /// 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 file name of the PCH file. + std::string FileName; + + /// \brief The memory buffer that stores the data associated with + /// this PCH file. + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + + /// \brief Offset type for all of the source location entries in the + /// PCH file. + const uint32_t *SLocOffsets; + + /// \brief The number of source location entries in the PCH file. + unsigned TotalNumSLocEntries; + + /// \brief Cursor used to read source location entries. + llvm::BitstreamCursor SLocEntryCursor; + + /// \brief Offset of each type within the bitstream, indexed by the + /// type ID, or the representation of a Type*. + const uint32_t *TypeOffsets; + + /// \brief Types that have already been loaded from the PCH file. + /// + /// When the pointer at index I is non-NULL, the type with + /// ID = (I + 1) << 3 has already been loaded from the PCH file. + std::vector<QualType> TypesLoaded; + + /// \brief Offset of each declaration within the bitstream, indexed + /// by the declaration ID (-1). + const uint32_t *DeclOffsets; + + /// \brief Declarations that have already been loaded from the PCH file. + /// + /// When the pointer at index I is non-NULL, the declaration with ID + /// = I + 1 has already been loaded. + std::vector<Decl *> DeclsLoaded; + + typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> > + DeclContextOffsetsMap; + + /// \brief Offsets of the lexical and visible declarations for each + /// DeclContext. + DeclContextOffsetsMap DeclContextOffsets; + + /// \brief Actual data for the on-disk hash table. + /// + // 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; + + /// \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 A vector containing identifiers that have already been + /// loaded. + /// + /// If the pointer at index I is non-NULL, then it refers to the + /// IdentifierInfo for the identifier with ID=I+1 that has already + /// been loaded. + std::vector<IdentifierInfo *> IdentifiersLoaded; + + /// \brief A pointer to an on-disk hash table of opaque type + /// PCHMethodPoolLookupTable. + /// + /// This hash table provides the instance and factory methods + /// associated with every selector known in the PCH file. + void *MethodPoolLookupTable; + + /// \brief A pointer to the character data that comprises the method + /// pool. + /// + /// The SelectorOffsets table refers into this memory. + const unsigned char *MethodPoolLookupTableData; + + /// \brief The number of selectors stored in the method pool itself. + unsigned TotalSelectorsInMethodPool; + + /// \brief Offsets into the method pool lookup table's data array + /// where each selector resides. + const uint32_t *SelectorOffsets; + + /// \brief The total number of selectors stored in the PCH file. + unsigned TotalNumSelectors; + + /// \brief A vector containing selectors that have already been loaded. + /// + /// This vector is indexed by the Selector ID (-1). NULL selector + /// entries indicate that the particular selector ID has not yet + /// been loaded. + llvm::SmallVector<Selector, 16> SelectorsLoaded; + + /// \brief Offsets of all of the macro definitions in the preprocessing + /// record in the PCH file. + const uint32_t *MacroDefinitionOffsets; + + /// \brief The macro definitions we have already loaded. + llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded; + + /// \brief The number of preallocated preprocessing entities in the + /// preprocessing record. + unsigned NumPreallocatedPreprocessingEntities; + + /// \brief The set of external definitions stored in the the PCH + /// file. + llvm::SmallVector<uint64_t, 16> ExternalDefinitions; + + /// \brief The set of tentative definitions stored in the the PCH + /// file. + llvm::SmallVector<uint64_t, 16> TentativeDefinitions; + + /// \brief The set of tentative definitions stored in the the PCH + /// file. + llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs; + + /// \brief The set of locally-scoped external declarations stored in + /// the the PCH file. + llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls; + + /// \brief The set of ext_vector type declarations stored in the the + /// PCH file. + llvm::SmallVector<uint64_t, 4> ExtVectorDecls; + + /// \brief The set of Objective-C category definitions stored in the + /// the PCH file. + llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls; + + /// \brief The original file name that was used to build the PCH file, which + /// may have been modified for relocatable-pch support. + std::string OriginalFileName; + + /// \brief The actual original file name that was used to build the PCH file. + std::string ActualOriginalFileName; + + /// \brief Whether this precompiled header is a relocatable PCH file. + bool RelocatablePCH; + + /// \brief The system include root to be used when loading the + /// precompiled header. + const char *isysroot; + + /// \brief Mapping from switch-case IDs in the PCH file to + /// switch-case statements. + std::map<unsigned, SwitchCase *> SwitchCaseStmts; + + /// \brief Mapping from label statement IDs in the PCH file to label + /// statements. + std::map<unsigned, LabelStmt *> LabelStmts; + + /// \brief Mapping from label IDs to the set of "goto" statements + /// that point to that label before the label itself has been + /// de-serialized. + std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts; + + /// \brief Mapping from label IDs to the set of address label + /// expressions that point to that label before the label itself has + /// been de-serialized. + std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs; + + /// \brief The number of stat() calls that hit/missed the stat + /// cache. + unsigned NumStatHits, NumStatMisses; + + /// \brief The number of source location entries de-serialized from + /// the PCH file. + unsigned NumSLocEntriesRead; + + /// \brief The number of statements (and expressions) de-serialized + /// from the PCH file. + unsigned NumStatementsRead; + + /// \brief The total number of statements (and expressions) stored + /// in the PCH file. + unsigned TotalNumStatements; + + /// \brief The number of macros de-serialized from the PCH file. + unsigned NumMacrosRead; + + /// \brief The number of method pool entries that have been read. + unsigned NumMethodPoolSelectorsRead; + + /// \brief The number of times we have looked into the global method + /// pool and not found anything. + unsigned NumMethodPoolMisses; + + /// \brief The total number of macros stored in the PCH file. + unsigned TotalNumMacros; + + /// Number of lexical decl contexts read/total. + unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts; + + /// Number of visible decl contexts read/total. + unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts; + + /// \brief When a type or declaration is being loaded from the PCH file, an + /// instantance of this RAII object will be available on the stack to + /// indicate when we are in a recursive-loading situation. + class LoadingTypeOrDecl { + PCHReader &Reader; + LoadingTypeOrDecl *Parent; + + LoadingTypeOrDecl(const LoadingTypeOrDecl&); // do not implement + LoadingTypeOrDecl &operator=(const LoadingTypeOrDecl&); // do not implement + + public: + explicit LoadingTypeOrDecl(PCHReader &Reader); + ~LoadingTypeOrDecl(); + }; + friend class LoadingTypeOrDecl; + + /// \brief If we are currently loading a type or declaration, points to the + /// most recent LoadingTypeOrDecl object on the stack. + LoadingTypeOrDecl *CurrentlyLoadingTypeOrDecl; + + /// \brief An IdentifierInfo that has been loaded but whose top-level + /// declarations of the same name have not (yet) been loaded. + struct PendingIdentifierInfo { + IdentifierInfo *II; + llvm::SmallVector<uint32_t, 4> DeclIDs; + }; + + /// \brief The set of identifiers that were read while the PCH reader was + /// (recursively) loading declarations. + /// + /// The declarations on the identifier chain for these identifiers will be + /// loaded once the recursive loading has completed. + std::deque<PendingIdentifierInfo> PendingIdentifierInfos; + + /// \brief FIXME: document! + llvm::SmallVector<uint64_t, 16> SpecialTypes; + + /// \brief Contains declarations and definitions that will be + /// "interesting" to the ASTConsumer, when we get that AST consumer. + /// + /// "Interesting" declarations are those that have data that may + /// need to be emitted, such as inline function definitions or + /// Objective-C protocols. + llvm::SmallVector<Decl *, 16> InterestingDecls; + + /// \brief The file ID for the predefines buffer in the PCH file. + FileID PCHPredefinesBufferID; + + /// \brief Pointer to the beginning of the predefines buffer in the + /// PCH file. + const char *PCHPredefines; + + /// \brief Length of the predefines buffer in the PCH file. + unsigned PCHPredefinesLen; + + /// \brief Suggested contents of the predefines buffer, after this + /// PCH file has been processed. + /// + /// In most cases, this string will be empty, because the predefines + /// buffer computed to build the PCH file will be identical to the + /// predefines buffer computed from the command line. However, when + /// there are differences that the PCH reader can work around, this + /// predefines buffer may contain additional definitions. + std::string SuggestedPredefines; + + void MaybeAddSystemRootToFilename(std::string &Filename); + + PCHReadResult ReadPCHBlock(); + bool CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID); + bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record); + PCHReadResult ReadSourceManagerBlock(); + PCHReadResult ReadSLocEntryRecord(unsigned ID); + + bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record); + QualType ReadTypeRecord(uint64_t Offset); + void LoadedDecl(unsigned Index, Decl *D); + Decl *ReadDeclRecord(uint64_t Offset, unsigned Index); + + /// \brief Produce an error diagnostic and return true. + /// + /// This routine should only be used for fatal errors that have to + /// do with non-routine failures (e.g., corrupted PCH file). + void Error(const char *Msg); + + PCHReader(const PCHReader&); // do not implement + PCHReader &operator=(const PCHReader &); // do not implement +public: + typedef llvm::SmallVector<uint64_t, 64> RecordData; + + /// \brief Load the PCH file and validate its contents against the given + /// Preprocessor. + /// + /// \param PP the preprocessor associated with the context in which this + /// precompiled header will be loaded. + /// + /// \param Context the AST context that this precompiled header will be + /// loaded into. + /// + /// \param isysroot If non-NULL, the system include path specified by the + /// user. This is only used with relocatable PCH files. If non-NULL, + /// a relocatable PCH file will use the default path "/". + PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0); + + /// \brief Load the PCH file without using any pre-initialized Preprocessor. + /// + /// The necessary information to initialize a Preprocessor later can be + /// obtained by setting a PCHReaderListener. + /// + /// \param SourceMgr the source manager into which the precompiled header + /// will be loaded. + /// + /// \param FileMgr the file manager into which the precompiled header will + /// be loaded. + /// + /// \param Diags the diagnostics system to use for reporting errors and + /// warnings relevant to loading the precompiled header. + /// + /// \param isysroot If non-NULL, the system include path specified by the + /// user. This is only used with relocatable PCH files. If non-NULL, + /// a relocatable PCH file will use the default path "/". + PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, + Diagnostic &Diags, const char *isysroot = 0); + ~PCHReader(); + + /// \brief Load the precompiled header designated by the given file + /// name. + PCHReadResult ReadPCH(const std::string &FileName); + + /// \brief Set the PCH callbacks listener. + void setListener(PCHReaderListener *listener) { + Listener.reset(listener); + } + + /// \brief Set the Preprocessor to use. + void setPreprocessor(Preprocessor &pp); + + /// \brief Sets and initializes the given Context. + void InitializeContext(ASTContext &Context); + + /// \brief Retrieve the name of the PCH file + const std::string &getFileName() { return FileName; } + + /// \brief Retrieve the name of the original source file name + const std::string &getOriginalSourceFile() { return OriginalFileName; } + + /// \brief Retrieve the name of the original source file name + /// directly from the PCH file, without actually loading the PCH + /// file. + static std::string getOriginalSourceFile(const std::string &PCHFileName, + Diagnostic &Diags); + + /// \brief Returns the suggested contents of the predefines buffer, + /// which contains a (typically-empty) subset of the predefines + /// build prior to including the precompiled header. + const std::string &getSuggestedPredefines() { return SuggestedPredefines; } + + /// \brief Read preprocessed entities into the + virtual void ReadPreprocessedEntities(); + + /// \brief Reads a TemplateArgumentLocInfo appropriate for the + /// given TemplateArgument kind. + TemplateArgumentLocInfo + GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + const RecordData &Record, unsigned &Idx); + + /// \brief Reads a declarator info from the given record. + virtual TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, + unsigned &Idx); + + /// \brief Resolve a type ID into a type, potentially building a new + /// type. + virtual QualType GetType(pch::TypeID ID); + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + virtual Decl *GetDecl(pch::DeclID ID); + + /// \brief Resolve the offset of a statement into a statement. + /// + /// This operation will read a new statement from the external + /// source each time it is called, and is meant to be used via a + /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). + virtual Stmt *GetDeclStmt(uint64_t Offset); + + /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the + /// specified cursor. Read the abbreviations that are at the top of the block + /// and then leave the cursor pointing into the block. + bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); + + /// \brief Read all of the declarations lexically stored in a + /// declaration context. + /// + /// \param DC The declaration context whose declarations will be + /// read. + /// + /// \param Decls Vector that will contain the declarations loaded + /// from the external source. The caller is responsible for merging + /// these declarations with any declarations already stored in the + /// declaration context. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, + llvm::SmallVectorImpl<pch::DeclID> &Decls); + + /// \brief Read all of the declarations visible from a declaration + /// context. + /// + /// \param DC The declaration context whose visible declarations + /// will be read. + /// + /// \param Decls A vector of visible declaration structures, + /// providing the mapping from each name visible in the declaration + /// context to the declaration IDs of declarations with that name. + /// + /// \returns true if there was an error while reading the + /// declarations for this declaration context. + /// + /// FIXME: Using this intermediate data structure results in an + /// extraneous copying of the data. Could we pass in a reference to + /// the StoredDeclsMap instead? + virtual bool ReadDeclsVisibleInContext(DeclContext *DC, + llvm::SmallVectorImpl<VisibleDeclaration> & Decls); + + /// \brief Function that will be invoked when we begin parsing a new + /// translation unit involving this external AST source. + /// + /// This function will provide all of the external definitions to + /// the ASTConsumer. + virtual void StartTranslationUnit(ASTConsumer *Consumer); + + /// \brief Print some statistics about PCH usage. + virtual void PrintStats(); + + /// \brief Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S); + + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() { SemaObj = 0; } + + /// \brief Retrieve the IdentifierInfo for the named identifier. + /// + /// This routine builds a new IdentifierInfo for the given identifier. If any + /// declarations with this name are visible from translation unit scope, their + /// declarations will be deserialized and introduced into the declaration + /// chain of the identifier. + virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd); + IdentifierInfo *get(llvm::StringRef Name) { + return get(Name.begin(), Name.end()); + } + + /// \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); + + void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); + void SetGloballyVisibleDecls(IdentifierInfo *II, + const llvm::SmallVectorImpl<uint32_t> &DeclIDs, + bool Nonrecursive = false); + + /// \brief Report a diagnostic. + DiagnosticBuilder Diag(unsigned DiagID); + + /// \brief Report a diagnostic. + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + + IdentifierInfo *DecodeIdentifierInfo(unsigned Idx); + + IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx) { + return DecodeIdentifierInfo(Record[Idx++]); + } + + virtual IdentifierInfo *GetIdentifier(unsigned ID) { + return DecodeIdentifierInfo(ID); + } + + /// \brief Read the source location entry with index ID. + virtual void ReadSLocEntry(unsigned ID); + + Selector DecodeSelector(unsigned Idx); + + virtual Selector GetSelector(uint32_t ID); + virtual uint32_t GetNumKnownSelectors(); + + Selector GetSelector(const RecordData &Record, unsigned &Idx) { + return DecodeSelector(Record[Idx++]); + } + + /// \brief Read a declaration name. + DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx); + + NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record, + unsigned &Idx); + + /// \brief Read a source location. + SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) { + return SourceLocation::getFromRawEncoding(Record[Idx++]); + } + + /// \brief Read a source range. + SourceRange ReadSourceRange(const RecordData &Record, unsigned& Idx); + + /// \brief Read an integral value + llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx); + + /// \brief Read a signed integral value + llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx); + + /// \brief Read a floating-point value + llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx); + + // \brief Read a string + std::string ReadString(const RecordData &Record, unsigned &Idx); + + CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); + + /// \brief Reads attributes from the current stream position. + Attr *ReadAttributes(); + + /// \brief ReadDeclExpr - Reads an expression from the current decl cursor. + Expr *ReadDeclExpr(); + + /// \brief ReadTypeExpr - Reads an expression from the current type cursor. + Expr *ReadTypeExpr(); + + /// \brief Reads a statement from the specified cursor. + Stmt *ReadStmt(llvm::BitstreamCursor &Cursor); + + /// \brief Read a statement from the current DeclCursor. + Stmt *ReadDeclStmt() { + return ReadStmt(DeclsCursor); + } + + /// \brief Reads the macro record located at the given offset. + void ReadMacroRecord(uint64_t Offset); + + /// \brief Read the set of macros defined by this external macro source. + virtual void ReadDefinedMacros(); + + /// \brief Retrieve the macro definition with the given ID. + MacroDefinition *getMacroDefinition(pch::IdentID ID); + + /// \brief Retrieve the AST context that this PCH reader + /// supplements. + ASTContext *getContext() { return Context; } + + // \brief Contains declarations that were loaded before we have + // access to a Sema object. + llvm::SmallVector<NamedDecl *, 16> PreloadedDecls; + + /// \brief Retrieve the semantic analysis object used to analyze the + /// translation unit in which the precompiled header is being + /// imported. + Sema *getSema() { return SemaObj; } + + /// \brief Retrieve the stream that this PCH reader is reading from. + llvm::BitstreamCursor &getStream() { return Stream; } + llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; } + + /// \brief Retrieve the identifier table associated with the + /// preprocessor. + IdentifierTable &getIdentifierTable(); + + /// \brief Record that the given ID maps to the given switch-case + /// statement. + void RecordSwitchCaseID(SwitchCase *SC, unsigned ID); + + /// \brief Retrieve the switch-case statement with the given ID. + SwitchCase *getSwitchCaseWithID(unsigned ID); + + /// \brief Record that the given label statement has been + /// deserialized and has the given ID. + void RecordLabelStmt(LabelStmt *S, unsigned ID); + + /// \brief Set the label of the given statement to the label + /// identified by ID. + /// + /// Depending on the order in which the label and other statements + /// referencing that label occur, this operation may complete + /// immediately (updating the statement) or it may queue the + /// statement to be back-patched later. + void SetLabelOf(GotoStmt *S, unsigned ID); + + /// \brief Set the label of the given expression to the label + /// identified by ID. + /// + /// Depending on the order in which the label and other statements + /// referencing that label occur, this operation may complete + /// immediately (updating the statement) or it may queue the + /// statement to be back-patched later. + void SetLabelOf(AddrLabelExpr *S, unsigned ID); +}; + +/// \brief Helper class that saves the current stream position and +/// then restores it when destroyed. +struct SavedStreamPosition { + explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor) + : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { } + + ~SavedStreamPosition() { + Cursor.JumpToBit(Offset); + } + +private: + llvm::BitstreamCursor &Cursor; + uint64_t Offset; +}; + +inline void PCHValidator::Error(const char *Msg) { + Reader.Error(Msg); +} + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHWriter.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHWriter.h new file mode 100644 index 0000000..85f53b9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHWriter.h @@ -0,0 +1,362 @@ +//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- 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 PCHWriter class, which writes a precompiled +// header containing a serialized representation of a translation +// unit. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_PCH_WRITER_H +#define LLVM_CLANG_FRONTEND_PCH_WRITER_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" +#include "clang/Frontend/PCHBitCodes.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include <map> +#include <queue> + +namespace llvm { + class APFloat; + class APInt; + class BitstreamWriter; +} + +namespace clang { + +class ASTContext; +class NestedNameSpecifier; +class CXXBaseSpecifier; +class CXXBaseOrMemberInitializer; +class LabelStmt; +class MacroDefinition; +class MemorizeStatCalls; +class Preprocessor; +class Sema; +class SourceManager; +class SwitchCase; +class TargetInfo; + +/// A structure for putting "fast"-unqualified QualTypes into a +/// DenseMap. This uses the standard pointer hash function. +struct UnsafeQualTypeDenseMapInfo { + static inline bool isEqual(QualType A, QualType B) { return A == B; } + static inline QualType getEmptyKey() { + return QualType::getFromOpaquePtr((void*) 1); + } + static inline QualType getTombstoneKey() { + return QualType::getFromOpaquePtr((void*) 2); + } + static inline unsigned getHashValue(QualType T) { + assert(!T.getLocalFastQualifiers() && + "hash invalid for types with fast quals"); + uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); + } +}; + +/// \brief Writes a precompiled header containing the contents of a +/// translation unit. +/// +/// The PCHWriter class produces a bitstream containing the serialized +/// representation of a given abstract syntax tree and its supporting +/// data structures. This bitstream can be de-serialized via an +/// instance of the PCHReader class. +class PCHWriter { +public: + typedef llvm::SmallVector<uint64_t, 64> RecordData; + +private: + /// \brief The bitstream writer used to emit this precompiled header. + llvm::BitstreamWriter &Stream; + + /// \brief Stores a declaration or a type to be written to the PCH file. + class DeclOrType { + public: + DeclOrType(Decl *D) : Stored(D), IsType(false) { } + DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { } + + bool isType() const { return IsType; } + bool isDecl() const { return !IsType; } + + QualType getType() const { + assert(isType() && "Not a type!"); + return QualType::getFromOpaquePtr(Stored); + } + + Decl *getDecl() const { + assert(isDecl() && "Not a decl!"); + return static_cast<Decl *>(Stored); + } + + private: + void *Stored; + bool IsType; + }; + + /// \brief The declarations and types to emit. + std::queue<DeclOrType> DeclTypesToEmit; + + /// \brief Map that provides the ID numbers of each declaration within + /// the output stream. + /// + /// The ID numbers of declarations are consecutive (in order of + /// discovery) and start at 2. 1 is reserved for the translation + /// unit, while 0 is reserved for NULL. + llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs; + + /// \brief Offset of each declaration in the bitstream, indexed by + /// the declaration's ID. + std::vector<uint32_t> DeclOffsets; + + /// \brief Map that provides the ID numbers of each type within the + /// output stream. + /// + /// The ID numbers of types are consecutive (in order of discovery) + /// and start at 1. 0 is reserved for NULL. When types are actually + /// stored in the stream, the ID number is shifted by 2 bits to + /// allow for the const/volatile qualifiers. + /// + /// Keys in the map never have const/volatile qualifiers. + llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs; + + /// \brief Offset of each type in the bitstream, indexed by + /// the type's ID. + std::vector<uint32_t> TypeOffsets; + + /// \brief The type ID that will be assigned to the next new type. + pch::TypeID NextTypeID; + + /// \brief Map that provides the ID numbers of each identifier in + /// the output stream. + /// + /// The ID numbers for identifiers are consecutive (in order of + /// discovery), starting at 1. An ID of zero refers to a NULL + /// IdentifierInfo. + llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs; + + /// \brief Offsets of each of the identifier IDs into the identifier + /// table. + std::vector<uint32_t> IdentifierOffsets; + + /// \brief Map that provides the ID numbers of each Selector. + llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs; + + /// \brief Offset of each selector within the method pool/selector + /// table, indexed by the Selector ID (-1). + std::vector<uint32_t> SelectorOffsets; + + /// \brief A vector of all Selectors (ordered by ID). + std::vector<Selector> SelVector; + + /// \brief Offsets of each of the macro identifiers into the + /// bitstream. + /// + /// For each identifier that is associated with a macro, this map + /// provides the offset into the bitstream where that macro is + /// defined. + llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets; + + /// \brief Mapping from macro definitions (as they occur in the preprocessing + /// record) to the index into the macro definitions table. + llvm::DenseMap<const MacroDefinition *, pch::IdentID> MacroDefinitions; + + /// \brief Mapping from the macro definition indices in \c MacroDefinitions + /// to the corresponding offsets within the preprocessor block. + std::vector<uint32_t> MacroDefinitionOffsets; + + /// \brief Declarations encountered that might be external + /// definitions. + /// + /// We keep track of external definitions (as well as tentative + /// definitions) as we are emitting declarations to the PCH + /// file. The PCH file contains a separate record for these external + /// definitions, which are provided to the AST consumer by the PCH + /// reader. This is behavior is required to properly cope with, + /// e.g., tentative variable definitions that occur within + /// headers. The declarations themselves are stored as declaration + /// IDs, since they will be written out to an EXTERNAL_DEFINITIONS + /// record. + llvm::SmallVector<uint64_t, 16> ExternalDefinitions; + + /// \brief Statements that we've encountered while serializing a + /// declaration or type. + llvm::SmallVector<Stmt *, 8> StmtsToEmit; + + /// \brief Mapping from SwitchCase statements to IDs. + std::map<SwitchCase *, unsigned> SwitchCaseIDs; + + /// \brief Mapping from LabelStmt statements to IDs. + std::map<LabelStmt *, unsigned> LabelIDs; + + /// \brief The number of statements written to the PCH file. + unsigned NumStatements; + + /// \brief The number of macros written to the PCH file. + unsigned NumMacros; + + /// \brief The number of lexical declcontexts written to the PCH + /// file. + unsigned NumLexicalDeclContexts; + + /// \brief The number of visible declcontexts written to the PCH + /// file. + unsigned NumVisibleDeclContexts; + + void WriteBlockInfoBlock(); + void WriteMetadata(ASTContext &Context, const char *isysroot); + void WriteLanguageOptions(const LangOptions &LangOpts); + void WriteStatCache(MemorizeStatCalls &StatCalls, const char* isysroot); + void WriteSourceManagerBlock(SourceManager &SourceMgr, + const Preprocessor &PP, + const char* isysroot); + void WritePreprocessor(const Preprocessor &PP); + void WriteType(QualType T); + uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); + uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); + + void WriteMethodPool(Sema &SemaRef); + void WriteIdentifierTable(Preprocessor &PP); + void WriteAttributeRecord(const Attr *Attr); + + unsigned ParmVarDeclAbbrev; + void WriteDeclsBlockAbbrevs(); + void WriteDecl(ASTContext &Context, Decl *D); + +public: + /// \brief Create a new precompiled header writer that outputs to + /// the given bitstream. + PCHWriter(llvm::BitstreamWriter &Stream); + + /// \brief Write a precompiled header for the given semantic analysis. + /// + /// \param SemaRef a reference to the semantic analysis object that processed + /// the AST to be written into the precompiled header. + /// + /// \param StatCalls the object that cached all of the stat() calls made while + /// searching for source files and headers. + /// + /// \param isysroot if non-NULL, write a relocatable PCH file whose headers + /// are relative to the given system root. + /// + /// \param PPRec Record of the preprocessing actions that occurred while + /// preprocessing this file, e.g., macro instantiations + void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const char* isysroot); + + /// \brief Emit a source location. + void AddSourceLocation(SourceLocation Loc, RecordData &Record); + + /// \brief Emit a source range. + void AddSourceRange(SourceRange Range, RecordData &Record); + + /// \brief Emit an integral value. + void AddAPInt(const llvm::APInt &Value, RecordData &Record); + + /// \brief Emit a signed integral value. + void AddAPSInt(const llvm::APSInt &Value, RecordData &Record); + + /// \brief Emit a floating-point value. + void AddAPFloat(const llvm::APFloat &Value, RecordData &Record); + + /// \brief Emit a reference to an identifier. + void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record); + + /// \brief Emit a Selector (which is a smart pointer reference). + void AddSelectorRef(Selector, RecordData &Record); + + /// \brief Emit a CXXTemporary. + void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record); + + /// \brief Get the unique number used to refer to the given + /// identifier. + pch::IdentID getIdentifierRef(const IdentifierInfo *II); + + /// \brief Retrieve the offset of the macro definition for the given + /// identifier. + /// + /// The identifier must refer to a macro. + uint64_t getMacroOffset(const IdentifierInfo *II) { + assert(MacroOffsets.find(II) != MacroOffsets.end() && + "Identifier does not name a macro"); + return MacroOffsets[II]; + } + + /// \brief Retrieve the ID number corresponding to the given macro + /// definition. + pch::IdentID getMacroDefinitionID(MacroDefinition *MD); + + /// \brief Emit a reference to a type. + void AddTypeRef(QualType T, RecordData &Record); + + /// \brief Emits a reference to a declarator info. + void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record); + + /// \brief Emits a template argument location. + void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, + RecordData &Record); + + /// \brief Emit a reference to a declaration. + void AddDeclRef(const Decl *D, RecordData &Record); + + /// \brief Determine the declaration ID of an already-emitted + /// declaration. + pch::DeclID getDeclID(const Decl *D); + + /// \brief Emit a declaration name. + void AddDeclarationName(DeclarationName Name, RecordData &Record); + + /// \brief Emit a nested name specifier. + void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordData &Record); + + /// \brief Add a string to the given record. + void AddString(const std::string &Str, RecordData &Record); + + /// \brief Note that the identifier II occurs at the given offset + /// within the identifier table. + void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); + + /// \brief Note that the selector Sel occurs at the given offset + /// within the method pool/selector table. + void SetSelectorOffset(Selector Sel, uint32_t Offset); + + /// \brief Add the given statement or expression to the queue of + /// statements to emit. + /// + /// This routine should be used when emitting types and declarations + /// that have expressions as part of their formulation. Once the + /// type or declaration has been written, call FlushStmts() to write + /// the corresponding statements just after the type or + /// declaration. + void AddStmt(Stmt *S) { StmtsToEmit.push_back(S); } + + /// \brief Write the given subexpression to the bitstream. + void WriteSubStmt(Stmt *S); + + /// \brief Flush all of the statements and expressions that have + /// been added to the queue via AddStmt(). + void FlushStmts(); + + /// \brief Record an ID for the given switch-case statement. + unsigned RecordSwitchCaseID(SwitchCase *S); + + /// \brief Retrieve the ID for the given switch-case statement. + unsigned getSwitchCaseID(SwitchCase *S); + + /// \brief Retrieve the ID for the given label statement, which may + /// or may not have been emitted yet. + unsigned GetLabelID(LabelStmt *S); + + unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PathDiagnosticClients.h b/contrib/llvm/tools/clang/include/clang/Frontend/PathDiagnosticClients.h new file mode 100644 index 0000000..f8d2eeb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PathDiagnosticClients.h @@ -0,0 +1,32 @@ +//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- 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 interface to create different path diagostic clients. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H +#define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H + +#include <string> + +namespace clang { + +class PathDiagnosticClient; +class Preprocessor; + +PathDiagnosticClient* +CreateHTMLDiagnosticClient(const std::string& prefix, const Preprocessor &PP); + +PathDiagnosticClient* +CreatePlistDiagnosticClient(const std::string& prefix, const Preprocessor &PP, + PathDiagnosticClient *SubPD = 0); + +} // end clang namespace +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h new file mode 100644 index 0000000..891359b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h @@ -0,0 +1,102 @@ +//===--- PreprocessorOptionms.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ +#define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ + +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class Preprocessor; +class LangOptions; + +/// PreprocessorOptions - This class is used for passing the various options +/// used in preprocessor initialization to InitializePreprocessor(). +class PreprocessorOptions { +public: + std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; + std::vector<std::string> Includes; + std::vector<std::string> MacroIncludes; + + unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler + /// and target specific predefines. + + unsigned DetailedRecord : 1; /// Whether we should maintain a detailed + /// record of all macro definitions and + /// instantiations. + + /// The implicit PCH included at the start of the translation unit, or empty. + std::string ImplicitPCHInclude; + + /// The implicit PTH input included at the start of the translation unit, or + /// empty. + std::string ImplicitPTHInclude; + + /// If given, a PTH cache file to use for speeding up header parsing. + std::string TokenCache; + + /// \brief The set of file remappings, which take existing files on + /// the system (the first part of each pair) and gives them the + /// contents of other files on the system (the second part of each + /// pair). + std::vector<std::pair<std::string, std::string> > RemappedFiles; + + /// \brief The set of file-to-buffer remappings, which take existing files + /// on the system (the first part of each pair) and gives them the contents + /// of the specified memory buffer (the second part of each pair). + std::vector<std::pair<std::string, const llvm::MemoryBuffer *> > + RemappedFileBuffers; + + typedef std::vector<std::pair<std::string, std::string> >::const_iterator + remapped_file_iterator; + remapped_file_iterator remapped_file_begin() const { + return RemappedFiles.begin(); + } + remapped_file_iterator remapped_file_end() const { + return RemappedFiles.end(); + } + + typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: + const_iterator remapped_file_buffer_iterator; + remapped_file_buffer_iterator remapped_file_buffer_begin() const { + return RemappedFileBuffers.begin(); + } + remapped_file_buffer_iterator remapped_file_buffer_end() const { + return RemappedFileBuffers.end(); + } + +public: + PreprocessorOptions() : UsePredefines(true), DetailedRecord(false) {} + + void addMacroDef(llvm::StringRef Name) { + Macros.push_back(std::make_pair(Name, false)); + } + void addMacroUndef(llvm::StringRef Name) { + Macros.push_back(std::make_pair(Name, true)); + } + void addRemappedFile(llvm::StringRef From, llvm::StringRef To) { + RemappedFiles.push_back(std::make_pair(From, To)); + } + void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) { + RemappedFileBuffers.push_back(std::make_pair(From, To)); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h new file mode 100644 index 0000000..a712a3d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h @@ -0,0 +1,37 @@ +//===--- PreprocessorOutputOptions.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H + +namespace clang { + +/// PreprocessorOutputOptions - Options for controlling the C preprocessor +/// output (e.g., -E). +class PreprocessorOutputOptions { +public: + unsigned ShowCPP : 1; ///< Print normal preprocessed output. + unsigned ShowMacros : 1; ///< Print macro definitions. + unsigned ShowLineMarkers : 1; ///< Show #line markers. + unsigned ShowComments : 1; ///< Show comments. + unsigned ShowMacroComments : 1; ///< Show comments, even in macros. + +public: + PreprocessorOutputOptions() { + ShowCPP = 1; + ShowMacros = 0; + ShowLineMarkers = 1; + ShowComments = 0; + ShowMacroComments = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def new file mode 100644 index 0000000..f63761a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def @@ -0,0 +1,520 @@ +//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- 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 XML statement database structure as written in +// <TranslationUnit> sub-nodes of the XML document. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement +// node and possible sub-nodes follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer +// by reference attributes to this value (currently used only for Label). +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an +// expression by a "type" attribute. FN is internally used by clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. +// +// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of +// a statement in the source file(s). +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. +// +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef ATTRIBUTE_FILE_LOCATION_XML +# define ATTRIBUTE_FILE_LOCATION_XML \ + ATTRIBUTE_XML(getFilename(), "file") \ + ATTRIBUTE_XML(getLine(), "line") \ + ATTRIBUTE_XML(getColumn(), "col") \ + ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ + ATTRIBUTE_OPT_XML(getLine(), "endline") \ + ATTRIBUTE_OPT_XML(getColumn(), "endcol") +#endif + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +NODE_XML(Stmt, "Stmt_Unsupported") // fallback for unsupproted statements + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(NullStmt, "NullStmt") + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(CompoundStmt, "CompoundStmt") + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(size(), "num_stmts") + SUB_NODE_SEQUENCE_XML(Stmt) +END_NODE_XML + +NODE_XML(CaseStmt, "CaseStmt") // case expr: body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // body + SUB_NODE_XML(Expr) // expr + SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body; +END_NODE_XML + +NODE_XML(DefaultStmt, "DefaultStmt") // default: body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(LabelStmt, "LabelStmt") // Label: body; + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getName(), "name") // string + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // stmt1 + SUB_NODE_XML(Stmt) // stmt2 +END_NODE_XML + +NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(WhileStmt, "WhileStmt") // while (cond) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(DoStmt, "DoStmt") // do body while (cond); + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Stmt) // init + SUB_NODE_XML(Expr) // cond + SUB_NODE_XML(Expr) // inc + SUB_NODE_XML(Stmt) // body +END_NODE_XML + +NODE_XML(GotoStmt, "GotoStmt") // goto label; + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string + ATTRIBUTE_XML(getLabel(), "ref") // id string +END_NODE_XML + +NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ContinueStmt, "ContinueStmt") // continue + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(BreakStmt, "BreakStmt") // break + ATTRIBUTE_FILE_LOCATION_XML +END_NODE_XML + +NODE_XML(ReturnStmt, "ReturnStmt") // return expr; + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension + ATTRIBUTE_FILE_LOCATION_XML + // FIXME +END_NODE_XML + +NODE_XML(DeclStmt, "DeclStmt") // a declaration statement + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_SEQUENCE_XML(Decl) +END_NODE_XML + +// C++ statements +NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 .. + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getNumHandlers(), "num_handlers") + SUB_NODE_XML(CompoundStmt) + SUB_NODE_SEQUENCE_XML(CXXCatchStmt) +END_NODE_XML + +NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt + ATTRIBUTE_FILE_LOCATION_XML + SUB_NODE_XML(VarDecl) + SUB_NODE_XML(Stmt) +END_NODE_XML + +// Expressions +NODE_XML(PredefinedExpr, "PredefinedExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getIdentType(), "kind") + ENUM_XML(PredefinedExpr::Func, "__func__") + ENUM_XML(PredefinedExpr::Function, "__FUNCTION__") + ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__") + END_ENUM_XML +END_NODE_XML + +NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal + //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here? +END_NODE_XML + +NODE_XML(IntegerLiteral, "IntegerLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // (signed) integer +END_NODE_XML + +NODE_XML(CharacterLiteral, "CharacterLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // unsigned +END_NODE_XML + +NODE_XML(FloatingLiteral, "FloatingLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + // FIXME: output float as written in source (no approximation or the like) + //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float +END_NODE_XML + +NODE_XML(StringLiteral, "StringLiteral") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed + ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean +END_NODE_XML + +NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getOpcode(), "kind") + ENUM_XML(UnaryOperator::PostInc, "postinc") + ENUM_XML(UnaryOperator::PostDec, "postdec") + ENUM_XML(UnaryOperator::PreInc, "preinc") + ENUM_XML(UnaryOperator::PreDec, "predec") + ENUM_XML(UnaryOperator::AddrOf, "addrof") + ENUM_XML(UnaryOperator::Deref, "deref") + ENUM_XML(UnaryOperator::Plus, "plus") + ENUM_XML(UnaryOperator::Minus, "minus") + ENUM_XML(UnaryOperator::Not, "not") // bitwise not + ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not + ENUM_XML(UnaryOperator::Real, "__real") + ENUM_XML(UnaryOperator::Imag, "__imag") + ENUM_XML(UnaryOperator::Extension, "__extension__") + ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") + END_ENUM_XML + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getOpcode(), "kind") + ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd") + ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi") + ENUM_XML(BinaryOperator::Mul , "mul") + ENUM_XML(BinaryOperator::Div , "div") + ENUM_XML(BinaryOperator::Rem , "rem") + ENUM_XML(BinaryOperator::Add , "add") + ENUM_XML(BinaryOperator::Sub , "sub") + ENUM_XML(BinaryOperator::Shl , "shl") + ENUM_XML(BinaryOperator::Shr , "shr") + ENUM_XML(BinaryOperator::LT , "lt") + ENUM_XML(BinaryOperator::GT , "gt") + ENUM_XML(BinaryOperator::LE , "le") + ENUM_XML(BinaryOperator::GE , "ge") + ENUM_XML(BinaryOperator::EQ , "eq") + ENUM_XML(BinaryOperator::NE , "ne") + ENUM_XML(BinaryOperator::And , "and") // bitwise and + ENUM_XML(BinaryOperator::Xor , "xor") + ENUM_XML(BinaryOperator::Or , "or") // bitwise or + ENUM_XML(BinaryOperator::LAnd , "land") // boolean and + ENUM_XML(BinaryOperator::LOr , "lor") // boolean or + ENUM_XML(BinaryOperator::Assign , "assign") + ENUM_XML(BinaryOperator::MulAssign, "mulassign") + ENUM_XML(BinaryOperator::DivAssign, "divassign") + ENUM_XML(BinaryOperator::RemAssign, "remassign") + ENUM_XML(BinaryOperator::AddAssign, "addassign") + ENUM_XML(BinaryOperator::SubAssign, "subassign") + ENUM_XML(BinaryOperator::ShlAssign, "shlassign") + ENUM_XML(BinaryOperator::ShrAssign, "shrassign") + ENUM_XML(BinaryOperator::AndAssign, "andassign") + ENUM_XML(BinaryOperator::XorAssign, "xorassign") + ENUM_XML(BinaryOperator::OrAssign , "orassign") + ENUM_XML(BinaryOperator::Comma , "comma") + END_ENUM_XML + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 +END_NODE_XML + +// FIXME: is there a special class needed or is BinaryOperator sufficient? +//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator") + +NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3 + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 + SUB_NODE_XML(Expr) // expr3 +END_NODE_XML + +NODE_XML(OffsetOfExpr, "OffsetOfExpr") // offsetof(basetype, components) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getTypeSourceInfo()->getType()) + ATTRIBUTE_XML(getNumComponents(), "num_components") + SUB_NODE_SEQUENCE_XML(OffsetOfExpr::OffsetOfNode) +END_NODE_XML + +NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isSizeOf(), "is_sizeof") + ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type + ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert + SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" +END_NODE_XML + +NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2] + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 +END_NODE_XML + +NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isArrow(), "is_deref") + ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F + ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ImplicitCastExpr, "ImplicitCastExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) +END_NODE_XML + +NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] + SUB_NODE_XML(Expr) // init +END_NODE_XML + +NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr") + SUB_NODE_XML(Expr) // base +END_NODE_XML + +NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } }; + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id + ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned + SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN +END_NODE_XML + +NODE_XML(DesignatedInitExpr, "DesignatedInitExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +// GNU Extensions +NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getLabel(), "ref") // id string + SUB_NODE_XML(LabelStmt) // expr +END_NODE_XML + +NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression. + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(CompoundStmt) +END_NODE_XML + +NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1 + ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2 +END_NODE_XML + +NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // expr1 + SUB_NODE_XML(Expr) // expr2 + SUB_NODE_XML(Expr) // expr3 +END_NODE_XML + +NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +// C++ Expressions +NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_ENUM_XML(getStmtClass(), "kind") + ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast") + ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast") + ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast") + ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast") + END_ENUM_XML + ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code + SUB_NODE_XML(Expr) // expr +END_NODE_XML + +NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned + SUB_NODE_XML(Expr) // fnexpr + SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN +END_NODE_XML + +NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getValue(), "value") // boolean +END_NODE_XML + +NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type + ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert + SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" +END_NODE_XML + +NODE_XML(CXXThisExpr, "CXXThisExpr") // this + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) +END_NODE_XML + +NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr); + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) // NULL in case of "throw;" +END_NODE_XML + +NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr") + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getType()) + ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration) +END_NODE_XML + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_SPECIAL_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ATTRIBUTE_FILE_LOCATION_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML +#undef SUB_NODE_XML +#undef SUB_NODE_SEQUENCE_XML +#undef SUB_NODE_OPT_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h new file mode 100644 index 0000000..380a1dd --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h @@ -0,0 +1,52 @@ +//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- 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 concrete diagnostic client, which buffers the diagnostic messages. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_ +#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_ + +#include "clang/Basic/Diagnostic.h" +#include <vector> + +namespace clang { + +class Preprocessor; +class SourceManager; + +class TextDiagnosticBuffer : public DiagnosticClient { +public: + typedef std::vector<std::pair<SourceLocation, std::string> > DiagList; + typedef DiagList::iterator iterator; + typedef DiagList::const_iterator const_iterator; +private: + DiagList Errors, Warnings, Notes; +public: + const_iterator err_begin() const { return Errors.begin(); } + const_iterator err_end() const { return Errors.end(); } + + const_iterator warn_begin() const { return Warnings.begin(); } + const_iterator warn_end() const { return Warnings.end(); } + + const_iterator note_begin() const { return Notes.begin(); } + const_iterator note_end() const { return Notes.end(); } + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + + /// FlushDiagnostics - Flush the buffered diagnostics to an given + /// diagnostic engine. + void FlushDiagnostics(Diagnostic &Diags) const; +}; + +} // end namspace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h new file mode 100644 index 0000000..ec4392f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h @@ -0,0 +1,85 @@ +//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- 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 concrete diagnostic client, which prints the diagnostics to +// standard error. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ +#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { +class DiagnosticOptions; +class LangOptions; +class SourceManager; + +class TextDiagnosticPrinter : public DiagnosticClient { + llvm::raw_ostream &OS; + const LangOptions *LangOpts; + const DiagnosticOptions *DiagOpts; + + SourceLocation LastWarningLoc; + FullSourceLoc LastLoc; + unsigned LastCaretDiagnosticWasNote : 1; + unsigned OwnsOutputStream : 1; + + /// A string to prefix to error messages. + std::string Prefix; + +public: + TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags, + bool OwnsOutputStream = false); + virtual ~TextDiagnosticPrinter(); + + /// setPrefix - Set the diagnostic printer prefix string, which will be + /// printed at the start of any diagnostics. If empty, no prefix string is + /// used. + void setPrefix(std::string Value) { Prefix = Value; } + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { + LangOpts = &LO; + } + + void EndSourceFile() { + LangOpts = 0; + } + + void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM); + + void HighlightRange(const SourceRange &R, + const SourceManager &SrcMgr, + unsigned LineNo, FileID FID, + std::string &CaretLine, + const std::string &SourceLine); + + void EmitCaretDiagnostic(SourceLocation Loc, + SourceRange *Ranges, unsigned NumRanges, + const SourceManager &SM, + const FixItHint *Hints, + unsigned NumHints, + unsigned Columns, + unsigned OnMacroInst, + unsigned MacroSkipStart, + unsigned MacroSkipEnd); + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def new file mode 100644 index 0000000..069d718 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def @@ -0,0 +1,299 @@ +//===-- TypeXML.def - Metadata about Type XML nodes ------------*- 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 XML type info database as written in the +// <ReferenceSection>/<Types> sub-nodes of the XML document. Type nodes +// are referred by "type" reference attributes throughout the document. +// A type node never contains sub-nodes. +// The semantics of the attributes and enums are mostly self-documenting +// by looking at the appropriate internally used functions and values. +// The following macros are used: +// +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// type of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that type +// node follows. +// +// END_NODE_XML - Closes the attribute definition of the current node. +// +// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a +// string, which value uniquely identify the type. Other nodes may refer +// by "type" reference attributes to this value. +// +// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type +// nodes by a "type" attribute. FN is internally used by clang. +// +// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their +// declaration contexts by a "context" attribute. FN is internally used by +// clang. +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// used by clang. A boolean attribute have the values "0" or "1". +// +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, +// if the value is the empty string. FN is internally used by clang. +// +// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the +// empty string. FN is internally used by clang. +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// internally used by clang. +// +// END_ENUM_XML - Closes the enumeration definition of the current attribute. +// +//===----------------------------------------------------------------------===// + +#ifndef TYPE_ATTRIBUTE_XML +# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#endif + +#ifndef CONTEXT_ATTRIBUTE_XML +# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#endif + +NODE_XML(Type, "FIXME_Type") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getTypeClassName(), "unhandled_type_name") +END_NODE_XML + +NODE_XML(QualType, "CvQualifiedType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*' + ATTRIBUTE_OPT_XML(isLocalConstQualified(), "const") // boolean + ATTRIBUTE_OPT_XML(isLocalVolatileQualified(), "volatile") // boolean + ATTRIBUTE_OPT_XML(isLocalRestrictQualified(), "restrict") // boolean + ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC + ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned +END_NODE_XML + +NODE_XML(BuiltinType, "FundamentalType") + ID_ATTRIBUTE_XML + ATTRIBUTE_ENUM_XML(getKind(), "kind") + ENUM_XML(BuiltinType::Void, "void") + ENUM_XML(BuiltinType::Bool, "bool") + ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform + ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform + ENUM_XML(BuiltinType::SChar, "signed char") + ENUM_XML(BuiltinType::Short, "short"); + ENUM_XML(BuiltinType::Int, "int"); + ENUM_XML(BuiltinType::Long, "long"); + ENUM_XML(BuiltinType::LongLong, "long long"); + ENUM_XML(BuiltinType::Int128, "__int128_t"); + ENUM_XML(BuiltinType::UChar, "unsigned char"); + ENUM_XML(BuiltinType::UShort, "unsigned short"); + ENUM_XML(BuiltinType::UInt, "unsigned int"); + ENUM_XML(BuiltinType::ULong, "unsigned long"); + ENUM_XML(BuiltinType::ULongLong, "unsigned long long"); + ENUM_XML(BuiltinType::UInt128, "__uint128_t"); + ENUM_XML(BuiltinType::Float, "float"); + ENUM_XML(BuiltinType::Double, "double"); + ENUM_XML(BuiltinType::LongDouble, "long double"); + ENUM_XML(BuiltinType::WChar, "wchar_t"); + ENUM_XML(BuiltinType::Char16, "char16_t"); + ENUM_XML(BuiltinType::Char32, "char32_t"); + ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'. + ENUM_XML(BuiltinType::Overload, "overloaded"); + ENUM_XML(BuiltinType::Dependent, "dependent"); + END_ENUM_XML +END_NODE_XML + +NODE_XML(PointerType, "PointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(LValueReferenceType, "ReferenceType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(RValueReferenceType, "ReferenceType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) +END_NODE_XML + +NODE_XML(FunctionNoProtoType, "FunctionNoProtoType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(FunctionProtoType, "FunctionType") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getResultType(), "result_type") + ATTRIBUTE_OPT_XML(isVariadic(), "variadic") +END_NODE_XML + +NODE_XML(TypedefType, "Typedef") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType()) + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc) + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) +END_NODE_XML + +NODE_XML(BlockPointerType, "BlockPointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type +END_NODE_XML + +NODE_XML(MemberPointerType, "MemberPointerType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getPointeeType()) + ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member +END_NODE_XML + +NODE_XML(ConstantArrayType, "ArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getSize(), "size") // unsigned + ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier") + ENUM_XML(ArrayType::Normal, "") + ENUM_XML(ArrayType::Static, "static") + ENUM_XML(ArrayType::Star, "star") + END_ENUM_XML + ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier") // unsigned +END_NODE_XML + +NODE_XML(IncompleteArrayType, "IncompleteArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) +END_NODE_XML + +NODE_XML(VariableArrayType, "VariableArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + // note: the size expression is print at the point of declaration +END_NODE_XML + +NODE_XML(DependentSizedArrayType, "DependentSizedArrayType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + // FIXME: how to deal with size expression? +END_NODE_XML + +NODE_XML(VectorType, "VectorType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getNumElements(), "size") // unsigned +END_NODE_XML + +NODE_XML(ExtVectorType, "ExtVectorType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getElementType()) + ATTRIBUTE_XML(getNumElements(), "size") // unsigned +END_NODE_XML + +NODE_XML(TypeOfExprType, "TypeOfExprType") + ID_ATTRIBUTE_XML + // note: the typeof expression is print at the point of use +END_NODE_XML + +NODE_XML(TypeOfType, "TypeOfType") + ID_ATTRIBUTE_XML + TYPE_ATTRIBUTE_XML(getUnderlyingType()) +END_NODE_XML + + +NODE_XML(RecordType, "Record") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind") + ENUM_XML(TTK_Struct, "struct") + ENUM_XML(TTK_Union, "union") + ENUM_XML(TTK_Class, "class") + END_ENUM_XML + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(EnumType, "Enum") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string + CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) +END_NODE_XML + +NODE_XML(TemplateTypeParmType, "TemplateTypeParmType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(TemplateSpecializationType, "TemplateSpecializationType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ElaboratedType, "ElaboratedType") + ID_ATTRIBUTE_XML + ATTRIBUTE_ENUM_XML(getKeyword(), "keyword") + ENUM_XML(ETK_None, "none") + ENUM_XML(ETK_Typename, "typename") + ENUM_XML(ETK_Struct, "struct") + ENUM_XML(ETK_Union, "union") + ENUM_XML(ETK_Class, "class") + ENUM_XML(ETK_Enum, "enum") + END_ENUM_XML + TYPE_ATTRIBUTE_XML(getNamedType()) +END_NODE_XML + +NODE_XML(InjectedClassNameType, "InjectedClassNameType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentNameType, "DependentNameType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ObjCInterfaceType, "ObjCInterfaceType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(SubstTemplateTypeParmType, "SubstTemplateTypeParm") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentSizedExtVectorType, "DependentSizedExtVector") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(UnresolvedUsingType, "UnresolvedUsing") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentTypeOfExprType, "DependentTypeOfExpr") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DecltypeType, "Decltype") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentDecltypeType, "DependentDecltype") + ID_ATTRIBUTE_XML +END_NODE_XML + +//===----------------------------------------------------------------------===// +#undef NODE_XML +#undef ID_ATTRIBUTE_XML +#undef TYPE_ATTRIBUTE_XML +#undef CONTEXT_ATTRIBUTE_XML +#undef ATTRIBUTE_XML +#undef ATTRIBUTE_OPT_XML +#undef ATTRIBUTE_ENUM_XML +#undef ATTRIBUTE_ENUM_OPT_XML +#undef ENUM_XML +#undef END_ENUM_XML +#undef END_NODE_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h new file mode 100644 index 0000000..c1d4831 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h @@ -0,0 +1,93 @@ +//===--- Utils.h - Misc utilities for the front-end -------------*- 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 miscellaneous utilities for various front-end actions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_UTILS_H +#define LLVM_CLANG_FRONTEND_UTILS_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +class Triple; +} + +namespace clang { +class ASTConsumer; +class Decl; +class DependencyOutputOptions; +class Diagnostic; +class DiagnosticOptions; +class HeaderSearch; +class HeaderSearchOptions; +class IdentifierTable; +class LangOptions; +class MinimalAction; +class Preprocessor; +class PreprocessorOptions; +class PreprocessorOutputOptions; +class SourceManager; +class Stmt; +class TargetInfo; +class FrontendOptions; + +/// Normalize \arg File for use in a user defined #include directive (in the +/// predefines buffer). +std::string NormalizeDashIncludePath(llvm::StringRef File); + +/// Apply the header search options to get given HeaderSearch object. +void ApplyHeaderSearchOptions(HeaderSearch &HS, + const HeaderSearchOptions &HSOpts, + const LangOptions &Lang, + const llvm::Triple &triple); + +/// InitializePreprocessor - Initialize the preprocessor getting it and the +/// environment ready to process a single file. +void InitializePreprocessor(Preprocessor &PP, + const PreprocessorOptions &PPOpts, + const HeaderSearchOptions &HSOpts, + const FrontendOptions &FEOpts); + +/// ProcessWarningOptions - Initialize the diagnostic client and process the +/// warning options specified on the command line. +void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts); + +/// DoPrintPreprocessedInput - Implement -E mode. +void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS, + const PreprocessorOutputOptions &Opts); + +/// RewriteMacrosInInput - Implement -rewrite-macros mode. +void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS); + +/// RewriteMacrosInInput - A simple test for the TokenRewriter class. +void DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS); + +/// CreatePrintParserActionsAction - Return the actions implementation that +/// implements the -parse-print-callbacks option. +MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP, + llvm::raw_ostream* OS); + +/// CheckDiagnostics - Gather the expected diagnostics and check them. +bool CheckDiagnostics(Preprocessor &PP); + +/// AttachDependencyFileGen - Create a dependency file generator, and attach +/// it to the given preprocessor. This takes ownership of the output stream. +void AttachDependencyFileGen(Preprocessor &PP, + const DependencyOutputOptions &Opts); + +/// CacheTokens - Cache tokens for use with PCH. Note that this requires +/// a seekable stream. +void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h new file mode 100644 index 0000000..6f45e49 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h @@ -0,0 +1,98 @@ +//===-- VerifyDiagnosticsClient.h - Verifying Diagnostic Client -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H +#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { + +class Diagnostic; +class TextDiagnosticBuffer; + +/// VerifyDiagnosticsClient - Create a diagnostic client which will use markers +/// in the input source to check that all the emitted diagnostics match those +/// expected. +/// +/// USING THE DIAGNOSTIC CHECKER: +/// +/// Indicating that a line expects an error or a warning is simple. Put a +/// comment on the line that has the diagnostic, use: +/// +/// expected-{error,warning,note} +/// +/// to tag if it's an expected error or warning, and place the expected text +/// between {{ and }} markers. The full text doesn't have to be included, only +/// enough to ensure that the correct diagnostic was emitted. +/// +/// Here's an example: +/// +/// int A = B; // expected-error {{use of undeclared identifier 'B'}} +/// +/// You can place as many diagnostics on one line as you wish. To make the code +/// more readable, you can use slash-newline to separate out the diagnostics. +/// +/// The simple syntax above allows each specification to match exactly one +/// error. You can use the extended syntax to customize this. The extended +/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of +/// "error", "warning" or "note", and <n> is a positive integer. This allows the +/// diagnostic to appear as many times as specified. Example: +/// +/// void f(); // expected-note 2 {{previous declaration is here}} +/// +/// Regex matching mode may be selected by appending '-re' to type. Example: +/// +/// expected-error-re +/// +/// Examples matching error: "variable has incomplete type 'struct s'" +/// +/// // expected-error {{variable has incomplete type 'struct s'}} +/// // expected-error {{variable has incomplete type}} +/// +/// // expected-error-re {{variable has has type 'struct .'}} +/// // expected-error-re {{variable has has type 'struct .*'}} +/// // expected-error-re {{variable has has type 'struct (.*)'}} +/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}} +/// +class VerifyDiagnosticsClient : public DiagnosticClient { +public: + Diagnostic &Diags; + llvm::OwningPtr<DiagnosticClient> PrimaryClient; + llvm::OwningPtr<TextDiagnosticBuffer> Buffer; + Preprocessor *CurrentPreprocessor; + unsigned NumErrors; + +private: + void CheckDiagnostics(); + +public: + /// Create a new verifying diagnostic client, which will issue errors to \arg + /// PrimaryClient when a diagnostic does not match what is expected (as + /// indicated in the source file). The verifying diagnostic client takes + /// ownership of \arg PrimaryClient. + VerifyDiagnosticsClient(Diagnostic &Diags, DiagnosticClient *PrimaryClient); + ~VerifyDiagnosticsClient(); + + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP); + + virtual void EndSourceFile(); + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + + /// HadErrors - Check if there were any mismatches in expected diagnostics. + bool HadErrors(); +}; + +} // end namspace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h new file mode 100644 index 0000000..fc18dae --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h @@ -0,0 +1,174 @@ +//===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ASTLocation is Decl or a Stmt and its immediate Decl parent. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ASTLOCATION_H +#define LLVM_CLANG_INDEX_ASTLOCATION_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class raw_ostream; +} + +namespace clang { + class Decl; + class Stmt; + class NamedDecl; + +namespace idx { + class TranslationUnit; + +/// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's +/// immutable. +/// +/// ASTLocation is intended to be used as a "pointer" into the AST. It is either +/// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid +/// of context, its parent Decl provides all the additional missing information +/// like the declaration context, ASTContext, etc. +/// +class ASTLocation { +public: + enum NodeKind { + N_Decl, N_NamedRef, N_Stmt, N_Type + }; + + struct NamedRef { + NamedDecl *ND; + SourceLocation Loc; + + NamedRef() : ND(0) { } + NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { } + }; + +private: + llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl; + + union { + Decl *D; + Stmt *Stm; + struct { + NamedDecl *ND; + unsigned RawLoc; + } NDRef; + struct { + void *TyPtr; + void *Data; + } Ty; + }; + +public: + ASTLocation() { } + + explicit ASTLocation(const Decl *d) + : ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { } + + ASTLocation(const Decl *parentDecl, const Stmt *stm) + : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt), + Stm(const_cast<Stmt*>(stm)) { + if (!stm) ParentDecl.setPointer(0); + } + + ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc) + : ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) { + if (ndRef) { + NDRef.ND = ndRef; + NDRef.RawLoc = loc.getRawEncoding(); + } else + ParentDecl.setPointer(0); + } + + ASTLocation(const Decl *parentDecl, TypeLoc tyLoc) + : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) { + if (tyLoc) { + Ty.TyPtr = tyLoc.getType().getAsOpaquePtr(); + Ty.Data = tyLoc.getOpaqueData(); + } else + ParentDecl.setPointer(0); + } + + 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; + } + Stmt *AsStmt() const { + assert(getKind() == N_Stmt); + return Stm; + } + NamedRef AsNamedRef() const { + assert(getKind() == N_NamedRef); + return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc)); + } + TypeLoc AsTypeLoc() const { + assert(getKind() == N_Type); + return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data); + } + + Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } + Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; } + NamedRef dyn_AsNamedRef() const { + return getKind() == N_Type ? AsNamedRef() : NamedRef(); + } + 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; } + bool isType() const { return isValid() && getKind() == N_Type; } + + /// \brief Returns the declaration that this ASTLocation references. + /// + /// If this points to a Decl, that Decl is returned. + /// If this points to an Expr that references a Decl, that Decl is returned, + /// otherwise it returns NULL. + Decl *getReferencedDecl(); + const Decl *getReferencedDecl() const { + return const_cast<ASTLocation*>(this)->getReferencedDecl(); + } + + SourceRange getSourceRange() const; + + void print(llvm::raw_ostream &OS) const; +}; + +/// \brief Like ASTLocation but also contains the TranslationUnit that the +/// ASTLocation originated from. +class TULocation : public ASTLocation { + TranslationUnit *TU; + +public: + TULocation(TranslationUnit *tu, ASTLocation astLoc) + : ASTLocation(astLoc), TU(tu) { + assert(tu && "Passed null translation unit"); + } + + TranslationUnit *getTU() const { return TU; } +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h b/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h new file mode 100644 index 0000000..f6b5465 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h @@ -0,0 +1,56 @@ +//===--- Analyzer.h - Analysis for indexing information ---------*- 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 Analyzer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ANALYZER_H +#define LLVM_CLANG_INDEX_ANALYZER_H + +namespace clang { + class Decl; + class ObjCMessageExpr; + +namespace idx { + class Program; + class IndexProvider; + class TULocationHandler; + +/// \brief Provides indexing information, like finding all references of an +/// Entity across translation units. +class Analyzer { + Program &Prog; + IndexProvider &Idxer; + + Analyzer(const Analyzer&); // do not implement + Analyzer &operator=(const Analyzer &); // do not implement + +public: + explicit Analyzer(Program &prog, IndexProvider &idxer) + : Prog(prog), Idxer(idxer) { } + + /// \brief Find all TULocations for declarations of the given Decl and pass + /// them to Handler. + void FindDeclarations(Decl *D, TULocationHandler &Handler); + + /// \brief Find all TULocations for references of the given Decl and pass + /// them to Handler. + void FindReferences(Decl *D, TULocationHandler &Handler); + + /// \brief Find methods that may respond to the given message and pass them + /// to Handler. + void FindObjCMethods(ObjCMessageExpr *MsgE, TULocationHandler &Handler); +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h new file mode 100644 index 0000000..5edfe6f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h @@ -0,0 +1,146 @@ +//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the CallGraph and CallGraphNode classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH +#define LLVM_CLANG_ANALYSIS_CALLGRAPH + +#include "clang/Index/ASTLocation.h" +#include "clang/Index/Entity.h" +#include "clang/Index/Program.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" +#include <vector> +#include <map> + +namespace clang { + +class CallGraphNode { + idx::Entity F; + typedef std::pair<idx::ASTLocation, CallGraphNode*> CallRecord; + std::vector<CallRecord> CalledFunctions; + +public: + CallGraphNode(idx::Entity f) : F(f) {} + + typedef std::vector<CallRecord>::iterator iterator; + typedef std::vector<CallRecord>::const_iterator const_iterator; + + iterator begin() { return CalledFunctions.begin(); } + iterator end() { return CalledFunctions.end(); } + const_iterator begin() const { return CalledFunctions.begin(); } + const_iterator end() const { return CalledFunctions.end(); } + + void addCallee(idx::ASTLocation L, CallGraphNode *Node) { + CalledFunctions.push_back(std::make_pair(L, Node)); + } + + bool hasCallee() const { return begin() != end(); } + + std::string getName() const { return F.getPrintableName(); } + + Decl *getDecl(ASTContext &Ctx) const { return F.getDecl(Ctx); } +}; + +class CallGraph { + /// Program manages all Entities. + idx::Program Prog; + + typedef std::map<idx::Entity, CallGraphNode *> FunctionMapTy; + + /// FunctionMap owns all CallGraphNodes. + FunctionMapTy FunctionMap; + + /// CallerCtx maps a caller to its ASTContext. + llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx; + + /// Root node is the 'main' function or 0. + CallGraphNode *Root; + + /// ExternalCallingNode has edges to all external functions. + CallGraphNode *ExternalCallingNode; + +public: + CallGraph(); + ~CallGraph(); + + 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(); } + + CallGraphNode *getRoot() { return Root; } + + CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; } + + void addTU(ASTContext &AST); + + idx::Program &getProgram() { return Prog; } + + CallGraphNode *getOrInsertFunction(idx::Entity F); + + Decl *getDecl(CallGraphNode *Node); + + void print(llvm::raw_ostream &os); + void dump(); + + void ViewCallGraph() const; +}; + +} // end clang namespace + +namespace llvm { + +template <> struct GraphTraits<clang::CallGraph> { + typedef clang::CallGraph GraphType; + typedef clang::CallGraphNode NodeType; + + typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy; + typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun; + + typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType; + + static NodeType *getEntryNode(GraphType *CG) { + return CG->getExternalCallingNode(); + } + + static ChildIteratorType child_begin(NodeType *N) { + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); + } + static ChildIteratorType child_end(NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + typedef std::pair<clang::idx::Entity, NodeType*> PairTy; + typedef std::pointer_to_unary_function<PairTy, NodeType*> DerefFun; + + typedef mapped_iterator<GraphType::const_iterator, DerefFun> nodes_iterator; + + static nodes_iterator nodes_begin(const GraphType &CG) { + return map_iterator(CG.begin(), DerefFun(CGDeref)); + } + static nodes_iterator nodes_end(const GraphType &CG) { + return map_iterator(CG.end(), DerefFun(CGDeref)); + } + + static NodeType *CGNDeref(CGNPairTy P) { return P.second; } + + static NodeType *CGDeref(PairTy P) { return P.second; } +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h b/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h new file mode 100644 index 0000000..73f2fe5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h @@ -0,0 +1,50 @@ +//===--- DeclReferenceMap.h - Map Decls to their references -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DeclReferenceMap creates a mapping from Decls to the ASTLocations that +// reference them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_DECLREFERENCEMAP_H +#define LLVM_CLANG_INDEX_DECLREFERENCEMAP_H + +#include "clang/Index/ASTLocation.h" +#include "clang/Index/STLExtras.h" +#include <map> + +namespace clang { + class ASTContext; + class NamedDecl; + +namespace idx { + +/// \brief Maps NamedDecls with the ASTLocations that reference them. +/// +/// References are mapped and retrieved using the canonical decls. +class DeclReferenceMap { +public: + explicit DeclReferenceMap(ASTContext &Ctx); + + typedef std::multimap<NamedDecl*, ASTLocation> MapTy; + typedef pair_value_iterator<MapTy::iterator> astlocation_iterator; + + astlocation_iterator refs_begin(NamedDecl *D) const; + astlocation_iterator refs_end(NamedDecl *D) const; + bool refs_empty(NamedDecl *D) const; + +private: + mutable MapTy Map; +}; + +} // end idx namespace + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Entity.h b/contrib/llvm/tools/clang/include/clang/Index/Entity.h new file mode 100644 index 0000000..c2aab62 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Entity.h @@ -0,0 +1,144 @@ +//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Entity is a ASTContext-independent way to refer to declarations that are +// visible across translation units. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ENTITY_H +#define LLVM_CLANG_INDEX_ENTITY_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" +#include <string> + +namespace clang { + class ASTContext; + class Decl; + +namespace idx { + class Program; + class EntityImpl; + +/// \brief A ASTContext-independent way to refer to declarations. +/// +/// Entity is basically the link for declarations that are semantically the same +/// in multiple ASTContexts. A client will convert a Decl into an Entity and +/// later use that Entity to find the "same" Decl into another ASTContext. +/// Declarations that are semantically the same and visible across translation +/// units will be associated with the same Entity. +/// +/// An Entity may also refer to declarations that cannot be visible across +/// translation units, e.g. static functions with the same name in multiple +/// translation units will be associated with different Entities. +/// +/// Entities can be checked for equality but note that the same Program object +/// should be used when getting Entities. +/// +class Entity { + /// \brief Stores the Decl directly if it is not visible outside of its own + /// translation unit, otherwise it stores the associated EntityImpl. + llvm::PointerUnion<Decl *, EntityImpl *> Val; + + explicit Entity(Decl *D); + explicit Entity(EntityImpl *impl) : Val(impl) { } + friend class EntityGetter; + +public: + Entity() { } + + /// \brief Find the Decl that can be referred to by this entity. + Decl *getDecl(ASTContext &AST) const; + + /// \brief If this Entity represents a declaration that is internal to its + /// translation unit, getInternalDecl() returns it. + Decl *getInternalDecl() const { + assert(isInternalToTU() && "This Entity is not internal!"); + return Val.get<Decl *>(); + } + + /// \brief Get a printable name for debugging purpose. + std::string getPrintableName() const; + + /// \brief Get an Entity associated with the given Decl. + /// \returns invalid Entity if an Entity cannot refer to this Decl. + static Entity get(Decl *D, Program &Prog); + + /// \brief true if the Entity is not visible outside the trasnlation unit. + bool isInternalToTU() const { + assert(isValid() && "This Entity is not valid!"); + return Val.is<Decl *>(); + } + + bool isValid() const { return !Val.isNull(); } + bool isInvalid() const { return !isValid(); } + + void *getAsOpaquePtr() const { return Val.getOpaqueValue(); } + static Entity getFromOpaquePtr(void *Ptr) { + Entity Ent; + Ent.Val = llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue(Ptr); + return Ent; + } + + friend bool operator==(const Entity &LHS, const Entity &RHS) { + return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr(); + } + + // For use in a std::map. + friend bool operator < (const Entity &LHS, const Entity &RHS) { + return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr(); + } + + // For use in DenseMap/DenseSet. + static Entity getEmptyMarker() { + Entity Ent; + Ent.Val = + llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-1); + return Ent; + } + static Entity getTombstoneMarker() { + Entity Ent; + Ent.Val = + llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-2); + return Ent; + } +}; + +} // namespace idx + +} // namespace clang + +namespace llvm { +/// Define DenseMapInfo so that Entities can be used as keys in DenseMap and +/// DenseSets. +template<> +struct DenseMapInfo<clang::idx::Entity> { + static inline clang::idx::Entity getEmptyKey() { + return clang::idx::Entity::getEmptyMarker(); + } + + static inline clang::idx::Entity getTombstoneKey() { + return clang::idx::Entity::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::idx::Entity); + + static inline bool + isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) { + return LHS == RHS; + } +}; + +template <> +struct isPodLike<clang::idx::Entity> { static const bool value = true; }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h b/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h new file mode 100644 index 0000000..9cd83a8 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h @@ -0,0 +1,100 @@ +//===--- GlobalSelector.h - Cross-translation-unit "token" for selectors --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// GlobalSelector is a ASTContext-independent way to refer to selectors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_GLOBALSELECTOR_H +#define LLVM_CLANG_INDEX_GLOBALSELECTOR_H + +#include "llvm/ADT/DenseMap.h" +#include <string> + +namespace clang { + class ASTContext; + class Selector; + +namespace idx { + class Program; + +/// \brief A ASTContext-independent way to refer to selectors. +class GlobalSelector { + void *Val; + + explicit GlobalSelector(void *val) : Val(val) { } + +public: + GlobalSelector() : Val(0) { } + + /// \brief Get the ASTContext-specific selector. + Selector getSelector(ASTContext &AST) const; + + bool isValid() const { return Val != 0; } + bool isInvalid() const { return !isValid(); } + + /// \brief Get a printable name for debugging purpose. + std::string getPrintableName() const; + + /// \brief Get a GlobalSelector for the ASTContext-specific selector. + static GlobalSelector get(Selector Sel, Program &Prog); + + void *getAsOpaquePtr() const { return Val; } + + static GlobalSelector getFromOpaquePtr(void *Ptr) { + return GlobalSelector(Ptr); + } + + friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) { + return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr(); + } + + // For use in a std::map. + friend bool operator< (const GlobalSelector &LHS, const GlobalSelector &RHS) { + return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr(); + } + + // For use in DenseMap/DenseSet. + static GlobalSelector getEmptyMarker() { return GlobalSelector((void*)-1); } + static GlobalSelector getTombstoneMarker() { + return GlobalSelector((void*)-2); + } +}; + +} // namespace idx + +} // namespace clang + +namespace llvm { +/// Define DenseMapInfo so that GlobalSelectors can be used as keys in DenseMap +/// and DenseSets. +template<> +struct DenseMapInfo<clang::idx::GlobalSelector> { + static inline clang::idx::GlobalSelector getEmptyKey() { + return clang::idx::GlobalSelector::getEmptyMarker(); + } + + static inline clang::idx::GlobalSelector getTombstoneKey() { + return clang::idx::GlobalSelector::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::idx::GlobalSelector); + + static inline bool + isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) { + return LHS == RHS; + } +}; + +template <> +struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Handlers.h b/contrib/llvm/tools/clang/include/clang/Index/Handlers.h new file mode 100644 index 0000000..655aef9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Handlers.h @@ -0,0 +1,81 @@ +//===--- Handlers.h - Interfaces for receiving information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstract interfaces for receiving information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_HANDLERS_H +#define LLVM_CLANG_INDEX_HANDLERS_H + +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +namespace idx { + class Entity; + class TranslationUnit; + class TULocation; + +/// \brief Abstract interface for receiving Entities. +class EntityHandler { +public: + typedef Entity receiving_type; + + virtual ~EntityHandler(); + virtual void Handle(Entity Ent) = 0; +}; + +/// \brief Abstract interface for receiving TranslationUnits. +class TranslationUnitHandler { +public: + typedef TranslationUnit* receiving_type; + + virtual ~TranslationUnitHandler(); + virtual void Handle(TranslationUnit *TU) = 0; +}; + +/// \brief Abstract interface for receiving TULocations. +class TULocationHandler { +public: + typedef TULocation receiving_type; + + virtual ~TULocationHandler(); + virtual void Handle(TULocation TULoc) = 0; +}; + +/// \brief Helper for the Handler classes. Stores the objects into a vector. +/// example: +/// @code +/// Storing<TranslationUnitHandler> TURes; +/// IndexProvider.GetTranslationUnitsFor(Entity, TURes); +/// for (Storing<TranslationUnitHandler>::iterator +/// I = TURes.begin(), E = TURes.end(); I != E; ++I) { .... +/// @endcode +template <typename handler_type> +class Storing : public handler_type { + typedef typename handler_type::receiving_type receiving_type; + typedef llvm::SmallVector<receiving_type, 8> StoreTy; + StoreTy Store; + +public: + virtual void Handle(receiving_type Obj) { + Store.push_back(Obj); + } + + typedef typename StoreTy::const_iterator iterator; + iterator begin() const { return Store.begin(); } + iterator end() const { return Store.end(); } +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h b/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h new file mode 100644 index 0000000..187dd93 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h @@ -0,0 +1,38 @@ +//===--- IndexProvider.h - Maps information to translation units -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Maps information to TranslationUnits. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXPROVIDER_H +#define LLVM_CLANG_INDEX_INDEXPROVIDER_H + +namespace clang { + +namespace idx { + class Entity; + class TranslationUnitHandler; + class GlobalSelector; + +/// \brief Maps information to TranslationUnits. +class IndexProvider { +public: + virtual ~IndexProvider(); + virtual void GetTranslationUnitsFor(Entity Ent, + TranslationUnitHandler &Handler) = 0; + virtual void GetTranslationUnitsFor(GlobalSelector Sel, + TranslationUnitHandler &Handler) = 0; +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Indexer.h b/contrib/llvm/tools/clang/include/clang/Index/Indexer.h new file mode 100644 index 0000000..361e729 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Indexer.h @@ -0,0 +1,64 @@ +//===--- Indexer.h - IndexProvider implementation ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// IndexProvider implementation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXER_H +#define LLVM_CLANG_INDEX_INDEXER_H + +#include "clang/Index/IndexProvider.h" +#include "clang/Index/Entity.h" +#include "clang/Index/GlobalSelector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include <map> + +namespace clang { + class ASTContext; + +namespace idx { + class Program; + class TranslationUnit; + +/// \brief Maps information to TranslationUnits. +class Indexer : public IndexProvider { +public: + typedef llvm::SmallPtrSet<TranslationUnit *, 4> TUSetTy; + typedef llvm::DenseMap<ASTContext *, TranslationUnit *> CtxTUMapTy; + typedef std::map<Entity, TUSetTy> MapTy; + typedef std::map<GlobalSelector, TUSetTy> SelMapTy; + + explicit Indexer(Program &prog) : + Prog(prog) { } + + Program &getProgram() const { return Prog; } + + /// \brief Find all Entities and map them to the given translation unit. + void IndexAST(TranslationUnit *TU); + + virtual void GetTranslationUnitsFor(Entity Ent, + TranslationUnitHandler &Handler); + virtual void GetTranslationUnitsFor(GlobalSelector Sel, + TranslationUnitHandler &Handler); + +private: + Program &Prog; + + MapTy Map; + CtxTUMapTy CtxTUMap; + SelMapTy SelMap; +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Program.h b/contrib/llvm/tools/clang/include/clang/Index/Program.h new file mode 100644 index 0000000..8039192 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Program.h @@ -0,0 +1,45 @@ +//===--- Program.h - Cross-translation unit information ---------*- 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 idx::Program interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_PROGRAM_H +#define LLVM_CLANG_INDEX_PROGRAM_H + +namespace clang { + class ASTContext; + +namespace idx { + class EntityHandler; + +/// \brief Top level object that owns and maintains information +/// that is common across translation units. +class Program { + void *Impl; + + Program(const Program&); // do not implement + Program &operator=(const Program &); // do not implement + friend class Entity; + friend class GlobalSelector; + +public: + Program(); + ~Program(); + + /// \brief Traverses the AST and passes all the entities to the Handler. + void FindEntities(ASTContext &Ctx, EntityHandler &Handler); +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h b/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h new file mode 100644 index 0000000..a3693c6 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h @@ -0,0 +1,63 @@ +//===--- STLExtras.h - Helper STL related templates -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Helper templates for using with the STL. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_STLEXTRAS_H +#define LLVM_CLANG_INDEX_STLEXTRAS_H + +namespace clang { + +namespace idx { + +/// \brief Wraps an iterator whose value_type is a pair, and provides +/// pair's second object as the value. +template <typename iter_type> +class pair_value_iterator { + iter_type I; + +public: + typedef typename iter_type::value_type::second_type value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef typename iter_type::iterator_category iterator_category; + typedef typename iter_type::difference_type difference_type; + + pair_value_iterator() { } + pair_value_iterator(iter_type i) : I(i) { } + + reference operator*() const { return I->second; } + pointer operator->() const { return &I->second; } + + pair_value_iterator& operator++() { + ++I; + return *this; + } + + pair_value_iterator operator++(int) { + pair_value_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(pair_value_iterator L, pair_value_iterator R) { + return L.I == R.I; + } + friend bool operator!=(pair_value_iterator L, pair_value_iterator R) { + return L.I != R.I; + } +}; + +} // end idx namespace + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h b/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h new file mode 100644 index 0000000..be01702 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h @@ -0,0 +1,57 @@ +//===--- SelectorMap.h - Maps selectors to methods and messages -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SelectorMap creates a mapping from selectors to ObjC method declarations +// and ObjC message expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_SELECTORMAP_H +#define LLVM_CLANG_INDEX_SELECTORMAP_H + +#include "clang/Index/ASTLocation.h" +#include "clang/Index/STLExtras.h" +#include "clang/Basic/IdentifierTable.h" +#include <map> + +namespace clang { + class ASTContext; + class ObjCMethodDecl; + +namespace idx { + +/// \brief Maps NamedDecls with the ASTLocations that reference them. +/// +/// References are mapped and retrieved using the canonical decls. +class SelectorMap { +public: + explicit SelectorMap(ASTContext &Ctx); + + typedef std::multimap<Selector, ObjCMethodDecl *> SelMethMapTy; + typedef std::multimap<Selector, ASTLocation> SelRefMapTy; + + typedef pair_value_iterator<SelMethMapTy::iterator> method_iterator; + typedef pair_value_iterator<SelRefMapTy::iterator> astlocation_iterator; + + method_iterator methods_begin(Selector Sel) const; + method_iterator methods_end(Selector Sel) const; + + astlocation_iterator refs_begin(Selector Sel) const; + astlocation_iterator refs_end(Selector Sel) const; + +private: + mutable SelMethMapTy SelMethMap; + mutable SelRefMapTy SelRefMap; +}; + +} // end idx namespace + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h b/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h new file mode 100644 index 0000000..bf9e78f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h @@ -0,0 +1,37 @@ +//===--- TranslationUnit.h - Interface for a translation unit ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstract interface for a translation unit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_TRANSLATIONUNIT_H +#define LLVM_CLANG_INDEX_TRANSLATIONUNIT_H + +namespace clang { + class ASTContext; + +namespace idx { + class DeclReferenceMap; + class SelectorMap; + +/// \brief Abstract interface for a translation unit. +class TranslationUnit { +public: + virtual ~TranslationUnit(); + virtual ASTContext &getASTContext() = 0; + virtual DeclReferenceMap &getDeclReferenceMap() = 0; + virtual SelectorMap &getSelectorMap() = 0; +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Index/Utils.h b/contrib/llvm/tools/clang/include/clang/Index/Utils.h new file mode 100644 index 0000000..f8e01f7 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Index/Utils.h @@ -0,0 +1,36 @@ +//===--- Utils.h - Misc utilities for indexing-----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains miscellaneous utilities for indexing related +// functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_UTILS_H +#define LLVM_CLANG_INDEX_UTILS_H + +namespace clang { + class ASTContext; + class SourceLocation; + +namespace idx { + class ASTLocation; + +/// \brief Returns the ASTLocation that a source location points to. +/// +/// \returns the resolved ASTLocation or an invalid ASTLocation if the source +/// location could not be resolved. +ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc, + ASTLocation *LastLoc = 0); + +} // end namespace idx + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h new file mode 100644 index 0000000..64687a1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h @@ -0,0 +1,134 @@ +//===--- DirectoryLookup.h - Info for searching for 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 defines the DirectoryLookup interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_DIRECTORYLOOKUP_H +#define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H + +#include "clang/Basic/SourceManager.h" + +namespace llvm { + class StringRef; +} +namespace clang { +class HeaderMap; +class DirectoryEntry; +class FileEntry; +class HeaderSearch; + +/// 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. +/// +class DirectoryLookup { +public: + enum LookupType_t { + LT_NormalDir, + LT_Framework, + LT_HeaderMap + }; +private: + union { // This union is discriminated by isHeaderMap. + /// Dir - This is the actual directory that we're referring to for a normal + /// directory or a framework. + const DirectoryEntry *Dir; + + /// Map - This is the HeaderMap if this is a headermap lookup. + /// + const HeaderMap *Map; + } u; + + /// DirCharacteristic - The type of directory this is: this is an instance of + /// SrcMgr::CharacteristicKind. + unsigned DirCharacteristic : 2; + + /// UserSupplied - True if this is a user-supplied directory. + /// + bool UserSupplied : 1; + + /// LookupType - This indicates whether this DirectoryLookup object is a + /// normal directory, a framework, or a headermap. + unsigned LookupType : 2; +public: + /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of + /// 'dir'. + DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT, + bool isUser, bool isFramework) + : DirCharacteristic(DT), UserSupplied(isUser), + LookupType(isFramework ? LT_Framework : LT_NormalDir) { + u.Dir = dir; + } + + /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of + /// 'map'. + DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT, + bool isUser) + : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) { + u.Map = map; + } + + /// getLookupType - Return the kind of directory lookup that this is: either a + /// normal directory, a framework path, or a HeaderMap. + LookupType_t getLookupType() const { return (LookupType_t)LookupType; } + + /// getName - Return the directory or filename corresponding to this lookup + /// object. + const char *getName() const; + + /// getDir - Return the directory that this entry refers to. + /// + const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; } + + /// getFrameworkDir - Return the directory that this framework refers to. + /// + const DirectoryEntry *getFrameworkDir() const { + return isFramework() ? u.Dir : 0; + } + + /// getHeaderMap - Return the directory that this entry refers to. + /// + const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; } + + /// isNormalDir - Return true if this is a normal directory, not a header map. + bool isNormalDir() const { return getLookupType() == LT_NormalDir; } + + /// isFramework - True if this is a framework directory. + /// + bool isFramework() const { return getLookupType() == LT_Framework; } + + /// isHeaderMap - Return true if this is a header map, not a normal directory. + bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } + + /// DirCharacteristic - The type of directory this is, one of the DirType enum + /// values. + SrcMgr::CharacteristicKind getDirCharacteristic() const { + return (SrcMgr::CharacteristicKind)DirCharacteristic; + } + + /// isUserSupplied - True if this is a user-supplied directory. + /// + bool isUserSupplied() const { return UserSupplied; } + + + /// LookupFile - Lookup the specified file in this search path, returning it + /// if it exists or returning null if not. + const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const; + +private: + const FileEntry *DoFrameworkLookup(llvm::StringRef Filename, + HeaderSearch &HS) const; + +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h new file mode 100644 index 0000000..af5c389 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h @@ -0,0 +1,34 @@ +//===- ExternalPreprocessorSource.h - Abstract Macro Interface --*- 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 ExternalPreprocessorSource interface, which enables +// construction of macro definitions from some external source. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H +#define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H + +namespace clang { + +/// \brief Abstract interface for external sources of preprocessor +/// information. +/// +/// This abstract class allows an external sources (such as the \c PCHReader) +/// to provide additional macro definitions. +class ExternalPreprocessorSource { +public: + virtual ~ExternalPreprocessorSource(); + + /// \brief Read the set of macros defined by this external macro source. + virtual void ReadDefinedMacros() = 0; +}; + +} + +#endif // LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h new file mode 100644 index 0000000..9837e29 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h @@ -0,0 +1,67 @@ +//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- 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 HeaderMap interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_HEADERMAP_H +#define LLVM_CLANG_LEX_HEADERMAP_H + +namespace llvm { + class MemoryBuffer; + class StringRef; +} +namespace clang { + class FileEntry; + class FileManager; + struct HMapBucket; + struct HMapHeader; + +/// This class represents an Apple concept known as a 'header map'. To the +/// #include file resolution process, it basically acts like a directory of +/// symlinks to files. Its advantages are that it is dense and more efficient +/// to create and process than a directory of symlinks. +class HeaderMap { + HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT + void operator=(const HeaderMap&); // DO NOT IMPLEMENT + + const llvm::MemoryBuffer *FileBuffer; + bool NeedsBSwap; + + HeaderMap(const llvm::MemoryBuffer *File, bool BSwap) + : FileBuffer(File), NeedsBSwap(BSwap) { + } +public: + ~HeaderMap(); + + /// HeaderMap::Create - This attempts to load the specified file as a header + /// map. If it doesn't look like a HeaderMap, it gives up and returns null. + static const HeaderMap *Create(const FileEntry *FE); + + /// LookupFile - Check to see if the specified relative filename is located in + /// this HeaderMap. If so, open it and return its FileEntry. + const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const; + + /// getFileName - Return the filename of the headermap. + const char *getFileName() const; + + /// dump - Print the contents of this headermap to stderr. + void dump() const; + +private: + unsigned getEndianAdjustedWord(unsigned X) const; + const HMapHeader &getHeader() const; + HMapBucket getBucket(unsigned BucketNo) const; + const char *getString(unsigned StrTabIdx) const; +}; + +} // end namespace clang. + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h new file mode 100644 index 0000000..978585c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h @@ -0,0 +1,235 @@ +//===--- HeaderSearch.h - Resolve Header File Locations ---------*- 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 HeaderSearch interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H +#define LLVM_CLANG_LEX_HEADERSEARCH_H + +#include "clang/Lex/DirectoryLookup.h" +#include "llvm/ADT/StringMap.h" +#include <vector> + +namespace clang { + +class ExternalIdentifierLookup; +class FileEntry; +class FileManager; +class IdentifierInfo; + +/// HeaderFileInfo - The preprocessor keeps track of this information for each +/// file that is #included. +struct HeaderFileInfo { + /// isImport - True if this is a #import'd or #pragma once file. + bool isImport : 1; + + /// DirInfo - Keep track of whether this is a system header, and if so, + /// whether it is C++ clean or not. This can be set by the include paths or + /// by #pragma gcc system_header. This is an instance of + /// SrcMgr::CharacteristicKind. + unsigned DirInfo : 2; + + /// NumIncludes - This is the number of times the file has been included + /// already. + unsigned short NumIncludes; + + /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard + /// that protects the entire contents of the file, this is the identifier + /// for the macro that controls whether or not it has any effect. + /// + /// Note: Most clients should use getControllingMacro() to access + /// the controlling macro of this header, since + /// getControllingMacro() is able to load a controlling macro from + /// external storage. + const IdentifierInfo *ControllingMacro; + + /// \brief The ID number of the controlling macro. + /// + /// This ID number will be non-zero when there is a controlling + /// macro whose IdentifierInfo may not yet have been loaded from + /// external storage. + unsigned ControllingMacroID; + + HeaderFileInfo() + : isImport(false), DirInfo(SrcMgr::C_User), + NumIncludes(0), ControllingMacro(0), ControllingMacroID(0) {} + + /// \brief Retrieve the controlling macro for this header file, if + /// any. + const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External); +}; + +/// HeaderSearch - This class encapsulates the information needed to find the +/// file referenced by a #include or #include_next, (sub-)framework lookup, etc. +class HeaderSearch { + FileManager &FileMgr; + + /// #include search path information. Requests for #include "x" search the + /// directory of the #including file first, then each directory in SearchDirs + /// consequtively. Requests for <x> search the current dir first, then each + /// directory in SearchDirs, starting at SystemDirIdx, consequtively. If + /// NoCurDirSearch is true, then the check for the file in the current + /// directory is supressed. + std::vector<DirectoryLookup> SearchDirs; + unsigned SystemDirIdx; + bool NoCurDirSearch; + + /// FileInfo - This contains all of the preprocessor-specific data about files + /// that are included. The vector is indexed by the FileEntry's UID. + /// + std::vector<HeaderFileInfo> FileInfo; + + /// LookupFileCache - This is keeps track of each lookup performed by + /// LookupFile. The first part of the value is the starting index in + /// SearchDirs that the cached search was performed from. If there is a hit + /// and this value doesn't match the current query, the cache has to be + /// ignored. The second value is the entry in SearchDirs that satisfied the + /// query. + llvm::StringMap<std::pair<unsigned, unsigned> > LookupFileCache; + + + /// FrameworkMap - This is a collection mapping a framework or subframework + /// name like "Carbon" to the Carbon.framework directory. + llvm::StringMap<const DirectoryEntry *> FrameworkMap; + + /// 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 Entity used to resolve the identifier IDs of controlling + /// macros into IdentifierInfo pointers, as needed. + ExternalIdentifierLookup *ExternalLookup; + + // Various statistics we track for performance analysis. + unsigned NumIncluded; + unsigned NumMultiIncludeFileOptzn; + unsigned NumFrameworkLookups, NumSubFrameworkLookups; + + // HeaderSearch doesn't support default or copy construction. + explicit HeaderSearch(); + explicit HeaderSearch(const HeaderSearch&); + void operator=(const HeaderSearch&); +public: + HeaderSearch(FileManager &FM); + ~HeaderSearch(); + + FileManager &getFileMgr() const { return FileMgr; } + + /// SetSearchPaths - Interface for setting the file search paths. + /// + void SetSearchPaths(const std::vector<DirectoryLookup> &dirs, + unsigned systemDirIdx, bool noCurDirSearch) { + SearchDirs = dirs; + SystemDirIdx = systemDirIdx; + NoCurDirSearch = noCurDirSearch; + //LookupFileCache.clear(); + } + + /// ClearFileInfo - Forget everything we know about headers so far. + void ClearFileInfo() { + FileInfo.clear(); + } + + void SetExternalLookup(ExternalIdentifierLookup *EIL) { + ExternalLookup = EIL; + } + + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, + /// return null on failure. isAngled indicates whether the file reference is + /// a <> reference. If successful, this returns 'UsedDir', the + /// DirectoryLookup member the file was found in, or null if not applicable. + /// If CurDir is non-null, the file was found in the specified directory + /// search location. This is used to implement #include_next. CurFileEnt, if + /// non-null, indicates where the #including file is, in case a relative + /// search is needed. + const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, + const DirectoryLookup *FromDir, + const DirectoryLookup *&CurDir, + const FileEntry *CurFileEnt); + + /// LookupSubframeworkHeader - Look up a subframework for the specified + /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from + /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox + /// is a subframework within Carbon.framework. If so, return the FileEntry + /// for the designated file, otherwise return null. + const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename, + const FileEntry *RelativeFileEnt); + + /// 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(llvm::StringRef FWName) { + return FrameworkMap.GetOrCreateValue(FWName).getValue(); + } + + /// ShouldEnterIncludeFile - Mark the specified file as a target of of a + /// #include, #include_next, or #import directive. Return false if #including + /// the file will have no effect or true if we should include it. + bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport); + + + /// getFileDirFlavor - Return whether the specified file is a normal header, + /// a system header, or a C++ friendly system header. + SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) { + return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; + } + + /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g. + /// due to #pragma once. + void MarkFileIncludeOnce(const FileEntry *File) { + getFileInfo(File).isImport = true; + } + + /// MarkFileSystemHeader - Mark the specified file as a system header, e.g. + /// due to #pragma GCC system_header. + void MarkFileSystemHeader(const FileEntry *File) { + getFileInfo(File).DirInfo = SrcMgr::C_System; + } + + /// IncrementIncludeCount - Increment the count for the number of times the + /// specified FileEntry has been entered. + void IncrementIncludeCount(const FileEntry *File) { + ++getFileInfo(File).NumIncludes; + } + + /// SetFileControllingMacro - Mark the specified file as having a controlling + /// macro. This is used by the multiple-include optimization to eliminate + /// no-op #includes. + void SetFileControllingMacro(const FileEntry *File, + const IdentifierInfo *ControllingMacro) { + getFileInfo(File).ControllingMacro = ControllingMacro; + } + + /// CreateHeaderMap - This method returns a HeaderMap for the specified + /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. + const HeaderMap *CreateHeaderMap(const FileEntry *FE); + + 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(); } + unsigned header_file_size() const { return FileInfo.size(); } + + // Used by PCHReader. + void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); + + void PrintStats(); +private: + + /// getFileInfo - Return the HeaderFileInfo structure for the specified + /// FileEntry. + HeaderFileInfo &getFileInfo(const FileEntry *FE); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h new file mode 100644 index 0000000..2d941e4 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticLex.h - Diagnostics for liblex ---------------*- 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_DIAGNOSTICLEX_H +#define LLVM_CLANG_DIAGNOSTICLEX_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define LEXSTART +#include "clang/Basic/DiagnosticLexKinds.inc" +#undef DIAG + NUM_BUILTIN_LEX_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h new file mode 100644 index 0000000..6a6e319 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h @@ -0,0 +1,384 @@ +//===--- Lexer.h - C Language Family Lexer ----------------------*- 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 Lexer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEXER_H +#define LLVM_CLANG_LEXER_H + +#include "clang/Lex/PreprocessorLexer.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/SmallVector.h" +#include <string> +#include <vector> +#include <cassert> + +namespace clang { +class Diagnostic; +class SourceManager; +class Preprocessor; +class DiagnosticBuilder; + +/// Lexer - This provides a simple interface that turns a text buffer into a +/// stream of tokens. This provides no support for file reading or buffering, +/// 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 { + //===--------------------------------------------------------------------===// + // 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). + bool Is_PragmaLexer : 1; // True if lexer for _Pragma handling. + bool IsInConflictMarker : 1; // True if in a VCS conflict marker '<<<<<<<' + + //===--------------------------------------------------------------------===// + // Context-specific lexing flags set by the preprocessor. + // + + /// ExtendedTokenMode - The lexer can optionally keep comments and whitespace + /// and return them as tokens. This is used for -C and -CC modes, and + /// whitespace preservation can be useful for some clients that want to lex + /// the file in raw mode and get every character from the file. + /// + /// When this is set to 2 it returns comments and whitespace. When set to 1 + /// it returns comments, when it is set to 0 it returns normal tokens only. + unsigned char ExtendedTokenMode; + + //===--------------------------------------------------------------------===// + // Context that changes as the file is lexed. + // NOTE: any state that mutates when in raw mode must have save/restore code + // in Lexer::isNextPPTokenLParen. + + // BufferPtr - Current pointer into the buffer. This is the next character + // to be lexed. + const char *BufferPtr; + + // IsAtStartOfLine - True if the next lexed token should get the "start of + // line" flag set on it. + bool IsAtStartOfLine; + + Lexer(const Lexer&); // DO NOT IMPLEMENT + void operator=(const Lexer&); // DO NOT IMPLEMENT + friend class Preprocessor; + + void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd); +public: + + /// Lexer constructor - Create a new lexer object for the specified buffer + /// with the specified preprocessor managing the lexing process. This lexer + /// assumes that the associated file buffer and Preprocessor objects will + /// outlive it, so it doesn't take ownership of either of them. + Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP); + + /// 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, + 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); + + /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for + /// _Pragma expansion. This has a variety of magic semantics that this method + /// sets up. It returns a new'd Lexer that must be delete'd when done. + static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc, + SourceLocation InstantiationLocStart, + SourceLocation InstantiationLocEnd, + 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; } + + /// getFileLoc - Return the File Location for the file we are lexing out of. + /// The physical location encodes the location where the characters come from, + /// the virtual location encodes where we should *claim* the characters came + /// from. Currently this is only used by _Pragma handling. + SourceLocation getFileLoc() const { return FileLoc; } + + /// Lex - Return the next token in the file. If this is the end of file, it + /// return the tok::eof token. Return true if an error occurred and + /// compilation should terminate, false if normal. This implicitly involves + /// the preprocessor. + void Lex(Token &Result) { + // Start a new token. + Result.startToken(); + + // NOTE, any changes here should also change code after calls to + // Preprocessor::HandleDirective + if (IsAtStartOfLine) { + Result.setFlag(Token::StartOfLine); + IsAtStartOfLine = false; + } + + // Get a token. Note that this may delete the current lexer if the end of + // file is reached. + LexTokenInternal(Result); + } + + /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma. + bool isPragmaLexer() const { return Is_PragmaLexer; } + + /// IndirectLex - An indirect call to 'Lex' that can be invoked via + /// the PreprocessorLexer interface. + void IndirectLex(Token &Result) { Lex(Result); } + + /// LexFromRawLexer - Lex a token from a designated raw lexer (one with no + /// associated preprocessor object. Return true if the 'next character to + /// read' pointer points at the end of the lexer buffer, false otherwise. + bool LexFromRawLexer(Token &Result) { + assert(LexingRawMode && "Not already in raw mode!"); + Lex(Result); + // Note that lexing to the end of the buffer doesn't implicitly delete the + // lexer when in raw mode. + return BufferPtr == BufferEnd; + } + + /// isKeepWhitespaceMode - Return true if the lexer should return tokens for + /// every character in the file, including whitespace and comments. This + /// should only be used in raw mode, as the preprocessor is not prepared to + /// deal with the excess tokens. + bool isKeepWhitespaceMode() const { + return ExtendedTokenMode > 1; + } + + /// SetKeepWhitespaceMode - This method lets clients enable or disable + /// whitespace retention mode. + void SetKeepWhitespaceMode(bool Val) { + assert((!Val || LexingRawMode) && + "Can only enable whitespace retention in raw mode"); + ExtendedTokenMode = Val ? 2 : 0; + } + + /// inKeepCommentMode - Return true if the lexer should return comments as + /// tokens. + bool inKeepCommentMode() const { + return ExtendedTokenMode > 0; + } + + /// SetCommentRetentionMode - Change the comment retention mode of the lexer + /// to the specified mode. This is really only useful when lexing in raw + /// mode, because otherwise the lexer needs to manage this. + void SetCommentRetentionState(bool Mode) { + assert(!isKeepWhitespaceMode() && + "Can't play with comment retention state when retaining whitespace"); + ExtendedTokenMode = Mode ? 1 : 0; + } + + const char *getBufferStart() const { return BufferStart; } + + /// ReadToEndOfLine - Read the rest of the current preprocessor line as an + /// uninterpreted string. This switches the lexer out of directive mode. + std::string ReadToEndOfLine(); + + + /// Diag - Forwarding function for diagnostics. This translate a source + /// position in the current buffer into a SourceLocation object for rendering. + DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const; + + /// getSourceLocation - Return a source location identifier for the specified + /// offset in the current file. + SourceLocation getSourceLocation(const char *Loc, unsigned TokLen = 1) const; + + /// getSourceLocation - Return a source location for the next character in + /// the current file. + SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); } + + /// \brief Return the current location in the buffer. + const char *getBufferLocation() const { return BufferPtr; } + + /// Stringify - Convert the specified string into a C string by escaping '\' + /// and " characters. This does not add surrounding ""'s to the string. + /// If Charify is true, this escapes the ' character instead of ". + static std::string Stringify(const std::string &Str, bool Charify = false); + + /// Stringify - Convert the specified string into a C string by escaping '\' + /// and " characters. This does not add surrounding ""'s to the string. + static void Stringify(llvm::SmallVectorImpl<char> &Str); + + /// MeasureTokenLength - Relex the token at the specified location and return + /// its length in bytes in the input file. If the token needs cleaning (e.g. + /// includes a trigraph or an escaped newline) then this count includes bytes + /// that are part of that. + static unsigned MeasureTokenLength(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); + + //===--------------------------------------------------------------------===// + // Internal implementation interfaces. +private: + + /// LexTokenInternal - Internal interface to lex a preprocessing token. Called + /// by Lex. + /// + void LexTokenInternal(Token &Result); + + /// FormTokenWithChars - When we lex a token, we have identified a span + /// starting at BufferPtr, going to TokEnd that forms the token. This method + /// takes that range and assigns it to the token as its location and size. In + /// addition, since tokens cannot overlap, this also updates BufferPtr to be + /// TokEnd. + void FormTokenWithChars(Token &Result, const char *TokEnd, + tok::TokenKind Kind) { + unsigned TokLen = TokEnd-BufferPtr; + Result.setLength(TokLen); + Result.setLocation(getSourceLocation(BufferPtr, TokLen)); + Result.setKind(Kind); + BufferPtr = TokEnd; + } + + /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a + /// tok::l_paren token, 0 if it is something else and 2 if there are no more + /// tokens in the buffer controlled by this lexer. + unsigned isNextPPTokenLParen(); + + //===--------------------------------------------------------------------===// + // Lexer character reading interfaces. +public: + + // This lexer is built on two interfaces for reading characters, both of which + // automatically provide phase 1/2 translation. getAndAdvanceChar is used + // when we know that we will be reading a character from the input buffer and + // that this character will be part of the result token. This occurs in (f.e.) + // string processing, because we know we need to read until we find the + // closing '"' character. + // + // The second interface is the combination of getCharAndSize with + // ConsumeChar. getCharAndSize reads a phase 1/2 translated character, + // returning it and its size. If the lexer decides that this character is + // part of the current token, it calls ConsumeChar on it. This two stage + // approach allows us to emit diagnostics for characters (e.g. warnings about + // trigraphs), knowing that they only are emitted if the character is + // consumed. + + /// isObviouslySimpleCharacter - Return true if the specified character is + /// obviously the same in translation phase 1 and translation phase 3. This + /// can return false for characters that end up being the same, but it will + /// never return true for something that needs to be mapped. + static bool isObviouslySimpleCharacter(char C) { + return C != '?' && C != '\\'; + } + + /// getAndAdvanceChar - Read a single 'character' from the specified buffer, + /// advance over it, and return it. This is tricky in several cases. Here we + /// just handle the trivial case and fall-back to the non-inlined + /// getCharAndSizeSlow method to handle the hard case. + inline char getAndAdvanceChar(const char *&Ptr, Token &Tok) { + // If this is not a trigraph and not a UCN or escaped newline, return + // quickly. + if (isObviouslySimpleCharacter(Ptr[0])) return *Ptr++; + + unsigned Size = 0; + char C = getCharAndSizeSlow(Ptr, Size, &Tok); + Ptr += Size; + return C; + } + +private: + /// ConsumeChar - When a character (identified by getCharAndSize) is consumed + /// and added to a given token, check to see if there are diagnostics that + /// need to be emitted or flags that need to be set on the token. If so, do + /// it. + const char *ConsumeChar(const char *Ptr, unsigned Size, Token &Tok) { + // Normal case, we consumed exactly one token. Just return it. + if (Size == 1) + return Ptr+Size; + + // Otherwise, re-lex the character with a current token, allowing + // diagnostics to be emitted and flags to be set. + Size = 0; + getCharAndSizeSlow(Ptr, Size, &Tok); + return Ptr+Size; + } + + /// getCharAndSize - Peek a single 'character' from the specified buffer, + /// get its size, and return it. This is tricky in several cases. Here we + /// just handle the trivial case and fall-back to the non-inlined + /// getCharAndSizeSlow method to handle the hard case. + inline char getCharAndSize(const char *Ptr, unsigned &Size) { + // If this is not a trigraph and not a UCN or escaped newline, return + // quickly. + if (isObviouslySimpleCharacter(Ptr[0])) { + Size = 1; + return *Ptr; + } + + Size = 0; + return getCharAndSizeSlow(Ptr, Size); + } + + /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize + /// method. + char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0); +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) { + // If this is not a trigraph and not a UCN or escaped newline, return + // quickly. + if (isObviouslySimpleCharacter(Ptr[0])) { + Size = 1; + return *Ptr; + } + + Size = 0; + return getCharAndSizeSlowNoWarn(Ptr, Size, Features); + } + + /// getEscapedNewLineSize - Return the size of the specified escaped newline, + /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry + /// to this function. + static unsigned getEscapedNewLineSize(const char *P); + + /// SkipEscapedNewLines - If P points to an escaped newline (or a series of + /// them), skip over them and return the first non-escaped-newline found, + /// otherwise return P. + static const char *SkipEscapedNewLines(const char *P); +private: + + /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a + /// diagnostic. + static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size, + const LangOptions &Features); + + //===--------------------------------------------------------------------===// + // Other lexer functions. + + // Helper functions to lex the remainder of a token of the specific type. + void LexIdentifier (Token &Result, const char *CurPtr); + void LexNumericConstant (Token &Result, const char *CurPtr); + void LexStringLiteral (Token &Result, const char *CurPtr,bool Wide); + void LexAngledStringLiteral(Token &Result, const char *CurPtr); + void LexCharConstant (Token &Result, const char *CurPtr); + bool LexEndOfFile (Token &Result, const char *CurPtr); + + bool SkipWhitespace (Token &Result, const char *CurPtr); + bool SkipBCPLComment (Token &Result, const char *CurPtr); + bool SkipBlockComment (Token &Result, const char *CurPtr); + bool SaveBCPLComment (Token &Result, const char *CurPtr); + + bool IsStartOfConflictMarker(const char *CurPtr); + bool HandleEndOfConflictMarker(const char *CurPtr); +}; + + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h new file mode 100644 index 0000000..ba46fb1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h @@ -0,0 +1,172 @@ +//===--- LiteralSupport.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 defines the NumericLiteralParser, CharLiteralParser, and +// StringLiteralParser interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_LITERALSUPPORT_H +#define CLANG_LITERALSUPPORT_H + +#include <string> +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/System/DataTypes.h" + +namespace clang { + +class Diagnostic; +class Preprocessor; +class Token; +class SourceLocation; +class TargetInfo; + +/// NumericLiteralParser - This performs strict semantic analysis of the content +/// of a ppnumber, classifying it as either integer, floating, or erroneous, +/// determines the radix of the value and can convert it to a useful value. +class NumericLiteralParser { + Preprocessor &PP; // needed for diagnostics + + const char *const ThisTokBegin; + const char *const ThisTokEnd; + const char *DigitsBegin, *SuffixBegin; // markers + const char *s; // cursor + + unsigned radix; + + bool saw_exponent, saw_period; + +public: + NumericLiteralParser(const char *begin, const char *end, + SourceLocation Loc, Preprocessor &PP); + bool hadError; + bool isUnsigned; + bool isLong; // This is *not* set for long long. + bool isLongLong; + bool isFloat; // 1.0f + bool isImaginary; // 1.0i + bool isMicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. + + bool isIntegerLiteral() const { + return !saw_period && !saw_exponent; + } + bool isFloatingLiteral() const { + return saw_period || saw_exponent; + } + bool hasSuffix() const { + return SuffixBegin != ThisTokEnd; + } + + unsigned getRadix() const { return radix; } + + /// GetIntegerValue - Convert this numeric literal value to an APInt that + /// matches Val's input width. If there is an overflow (i.e., if the unsigned + /// value read is larger than the APInt's bits will hold), set Val to the low + /// bits of the result and return true. Otherwise, return false. + bool GetIntegerValue(llvm::APInt &Val); + + /// GetFloatValue - Convert this numeric literal to a floating value, using + /// the specified APFloat fltSemantics (specifying float, double, etc). + /// The optional bool isExact (passed-by-reference) has its value + /// set to true if the returned APFloat can represent the number in the + /// literal exactly, and false otherwise. + llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + +private: + + void ParseNumberStartingWithZero(SourceLocation TokLoc); + + /// SkipHexDigits - Read and skip over any hex digits, up to End. + /// Return a pointer to the first non-hex digit or End. + const char *SkipHexDigits(const char *ptr) { + while (ptr != ThisTokEnd && isxdigit(*ptr)) + ptr++; + return ptr; + } + + /// SkipOctalDigits - Read and skip over any octal digits, up to End. + /// Return a pointer to the first non-hex digit or End. + const char *SkipOctalDigits(const char *ptr) { + while (ptr != ThisTokEnd && ((*ptr >= '0') && (*ptr <= '7'))) + ptr++; + return ptr; + } + + /// SkipDigits - Read and skip over any digits, up to End. + /// Return a pointer to the first non-hex digit or End. + const char *SkipDigits(const char *ptr) { + while (ptr != ThisTokEnd && isdigit(*ptr)) + ptr++; + return ptr; + } + + /// SkipBinaryDigits - Read and skip over any binary digits, up to End. + /// Return a pointer to the first non-binary digit or End. + const char *SkipBinaryDigits(const char *ptr) { + while (ptr != ThisTokEnd && (*ptr == '0' || *ptr == '1')) + ptr++; + return ptr; + } + +}; + +/// CharLiteralParser - Perform interpretation and semantic analysis of a +/// character literal. +class CharLiteralParser { + uint64_t Value; + bool IsWide; + bool IsMultiChar; + bool HadError; +public: + CharLiteralParser(const char *begin, const char *end, + SourceLocation Loc, Preprocessor &PP); + + bool hadError() const { return HadError; } + bool isWide() const { return IsWide; } + bool isMultiChar() const { return IsMultiChar; } + uint64_t getValue() const { return Value; } +}; + +/// StringLiteralParser - This decodes string escape characters and performs +/// wide string analysis and Translation Phase #6 (concatenation of string +/// literals) (C99 5.1.1.2p1). +class StringLiteralParser { + Preprocessor &PP; + + unsigned MaxTokenLength; + unsigned SizeBound; + unsigned wchar_tByteWidth; + llvm::SmallString<512> ResultBuf; + char *ResultPtr; // cursor +public: + StringLiteralParser(const Token *StringToks, unsigned NumStringToks, + Preprocessor &PP, bool Complain = true); + bool hadError; + bool AnyWide; + bool Pascal; + + const char *GetString() { return &ResultBuf[0]; } + unsigned GetStringLength() const { return ResultPtr-&ResultBuf[0]; } + + unsigned GetNumStringChars() const { + if (AnyWide) + return GetStringLength() / wchar_tByteWidth; + return GetStringLength(); + } + /// getOffsetOfStringByte - This function returns the offset of the + /// specified byte of the string data represented by Token. This handles + /// advancing over escape sequences in the string. + static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo, + Preprocessor &PP, bool Complain = true); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h new file mode 100644 index 0000000..5887041 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h @@ -0,0 +1,218 @@ +//===--- MacroInfo.h - Information about #defined identifiers ---*- 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 MacroInfo interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_MACROINFO_H +#define LLVM_CLANG_MACROINFO_H + +#include "clang/Lex/Token.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include <vector> +#include <cassert> + +namespace clang { + class Preprocessor; + +/// MacroInfo - Each identifier that is #define'd has an instance of this class +/// associated with it, used to implement macro expansion. +class MacroInfo { + //===--------------------------------------------------------------------===// + // State set when the macro is defined. + + /// Location - This is the place the macro is defined. + SourceLocation Location; + /// EndLocation - The location of the last token in the macro. + SourceLocation EndLocation; + + /// Arguments - The list of arguments for a function-like macro. This can be + /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this + /// includes the __VA_ARGS__ identifier on the list. + IdentifierInfo **ArgumentList; + unsigned NumArguments; + + /// ReplacementTokens - This is the list of tokens that the macro is defined + /// to. + llvm::SmallVector<Token, 8> ReplacementTokens; + + /// IsFunctionLike - True if this macro is a function-like macro, false if it + /// is an object-like macro. + bool IsFunctionLike : 1; + + /// IsC99Varargs - True if this macro is of the form "#define X(...)" or + /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the + /// contents of "..." in an invocation. + bool IsC99Varargs : 1; + + /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The + /// "a" identifier in the replacement list will be replaced with all arguments + /// of the macro starting with the specified one. + bool IsGNUVarargs : 1; + + /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if + /// it has not yet been redefined or undefined. + bool IsBuiltinMacro : 1; + +private: + //===--------------------------------------------------------------------===// + // State that changes as the macro is used. + + /// IsDisabled - True if we have started an expansion of this macro already. + /// This disbles recursive expansion, which would be quite bad for things like + /// #define A A. + bool IsDisabled : 1; + + /// IsUsed - True if this macro is either defined in the main file and has + /// been used, or if it is not defined in the main file. This is used to + /// emit -Wunused-macros diagnostics. + bool IsUsed : 1; + + ~MacroInfo() { + assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); + } + +public: + MacroInfo(SourceLocation DefLoc); + + /// FreeArgumentList - Free the argument list of the macro, restoring it to a + /// state where it can be reused for other devious purposes. + void FreeArgumentList(llvm::BumpPtrAllocator &PPAllocator) { + PPAllocator.Deallocate(ArgumentList); + ArgumentList = 0; + NumArguments = 0; + } + + /// Destroy - destroy this MacroInfo object. + void Destroy(llvm::BumpPtrAllocator &PPAllocator) { + FreeArgumentList(PPAllocator); + this->~MacroInfo(); + } + + /// getDefinitionLoc - Return the location that the macro was defined at. + /// + SourceLocation getDefinitionLoc() const { return Location; } + + /// setDefinitionEndLoc - Set the location of the last token in the macro. + /// + void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } + /// getDefinitionEndLoc - Return the location of the last token in the macro. + /// + SourceLocation getDefinitionEndLoc() const { return EndLocation; } + + /// isIdenticalTo - Return true if the specified macro definition is equal to + /// this macro in spelling, arguments, and whitespace. This is used to emit + /// duplicate definition warnings. This implements the rules in C99 6.10.3. + bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const; + + /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag. + /// + void setIsBuiltinMacro(bool Val = true) { + IsBuiltinMacro = Val; + } + + /// setIsUsed - Set the value of the IsUsed flag. + /// + void setIsUsed(bool Val) { + IsUsed = Val; + } + + /// setArgumentList - Set the specified list of identifiers as the argument + /// list for this macro. + void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, + llvm::BumpPtrAllocator &PPAllocator) { + assert(ArgumentList == 0 && NumArguments == 0 && + "Argument list already set!"); + if (NumArgs == 0) return; + + NumArguments = NumArgs; + ArgumentList = PPAllocator.Allocate<IdentifierInfo*>(NumArgs); + for (unsigned i = 0; i != NumArgs; ++i) + ArgumentList[i] = List[i]; + } + + /// Arguments - The list of arguments for a function-like macro. This can be + /// empty, for, e.g. "#define X()". + typedef IdentifierInfo* const *arg_iterator; + bool arg_empty() const { return NumArguments == 0; } + arg_iterator arg_begin() const { return ArgumentList; } + arg_iterator arg_end() const { return ArgumentList+NumArguments; } + unsigned getNumArgs() const { return NumArguments; } + + /// getArgumentNum - Return the argument number of the specified identifier, + /// or -1 if the identifier is not a formal argument identifier. + int getArgumentNum(IdentifierInfo *Arg) const { + for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I) + if (*I == Arg) return I-arg_begin(); + return -1; + } + + /// Function/Object-likeness. Keep track of whether this macro has formal + /// parameters. + void setIsFunctionLike() { IsFunctionLike = true; } + bool isFunctionLike() const { return IsFunctionLike; } + bool isObjectLike() const { return !IsFunctionLike; } + + /// Varargs querying methods. This can only be set for function-like macros. + void setIsC99Varargs() { IsC99Varargs = true; } + void setIsGNUVarargs() { IsGNUVarargs = true; } + bool isC99Varargs() const { return IsC99Varargs; } + bool isGNUVarargs() const { return IsGNUVarargs; } + bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; } + + /// isBuiltinMacro - Return true if this macro is a builtin macro, such as + /// __LINE__, which requires processing before expansion. + bool isBuiltinMacro() const { return IsBuiltinMacro; } + + /// isUsed - Return false if this macro is defined in the main file and has + /// not yet been used. + bool isUsed() const { return IsUsed; } + + /// getNumTokens - Return the number of tokens that this macro expands to. + /// + unsigned getNumTokens() const { + return ReplacementTokens.size(); + } + + const Token &getReplacementToken(unsigned Tok) const { + assert(Tok < ReplacementTokens.size() && "Invalid token #"); + return ReplacementTokens[Tok]; + } + + typedef llvm::SmallVector<Token, 8>::const_iterator tokens_iterator; + tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); } + tokens_iterator tokens_end() const { return ReplacementTokens.end(); } + bool tokens_empty() const { return ReplacementTokens.empty(); } + + /// AddTokenToBody - Add the specified token to the replacement text for the + /// macro. + void AddTokenToBody(const Token &Tok) { + ReplacementTokens.push_back(Tok); + } + + /// isEnabled - Return true if this macro is enabled: in other words, that we + /// are not currently in an expansion of this macro. + bool isEnabled() const { return !IsDisabled; } + + void EnableMacro() { + assert(IsDisabled && "Cannot enable an already-enabled macro!"); + IsDisabled = false; + } + + void DisableMacro() { + assert(!IsDisabled && "Cannot disable an already-disabled macro!"); + IsDisabled = true; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h new file mode 100644 index 0000000..5d5d673 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h @@ -0,0 +1,130 @@ +//===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- 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 MultipleIncludeOpt interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H +#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H + +namespace clang { +class IdentifierInfo; + +/// MultipleIncludeOpt - This class implements the simple state machine that the +/// Lexer class uses to detect files subject to the 'multiple-include' +/// optimization. The public methods in this class are triggered by various +/// events that occur when a file is lexed, and after the entire file is lexed, +/// information about which macro (if any) controls the header is returned. +class MultipleIncludeOpt { + /// ReadAnyTokens - This is set to false when a file is first opened and true + /// any time a token is returned to the client or a (non-multiple-include) + /// directive is parsed. When the final #endif is parsed this is reset back + /// to false, that way any tokens before the first #ifdef or after the last + /// #endif can be easily detected. + bool ReadAnyTokens; + + /// ReadAnyTokens - This is set to false when a file is first opened and true + /// any time a token is returned to the client or a (non-multiple-include) + /// directive is parsed. When the final #endif is parsed this is reset back + /// to false, that way any tokens before the first #ifdef or after the last + /// #endif can be easily detected. + bool DidMacroExpansion; + + /// TheMacro - The controlling macro for a file, if valid. + /// + const IdentifierInfo *TheMacro; +public: + MultipleIncludeOpt() { + ReadAnyTokens = false; + DidMacroExpansion = false; + TheMacro = 0; + } + + /// Invalidate - Permenantly mark this file as not being suitable for the + /// include-file optimization. + void Invalidate() { + // If we have read tokens but have no controlling macro, the state-machine + // below can never "accept". + ReadAnyTokens = true; + TheMacro = 0; + } + + /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the + /// top of the file when reading preprocessor directives. Otherwise, reading + /// the "ifndef x" would count as reading tokens. + bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } + + // If a token is read, remember that we have seen a side-effect in this file. + void ReadToken() { ReadAnyTokens = true; } + + /// ExpandedMacro - When a macro is expanded with this lexer as the current + /// buffer, this method is called to disable the MIOpt if needed. + void ExpandedMacro() { DidMacroExpansion = true; } + + /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the + /// "#if !defined" equivalent) without any preceding tokens, this method is + /// called. + /// + /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller + /// ensures that this is only called if there are no tokens read before the + /// #ifndef. The caller is required to do this, because reading the #if line + /// obviously reads in in tokens. + void EnterTopLevelIFNDEF(const IdentifierInfo *M) { + // If the macro is already set, this is after the top-level #endif. + if (TheMacro) + return Invalidate(); + + // If we have already expanded a macro by the end of the #ifndef line, then + // there is a macro expansion *in* the #ifndef line. This means that the + // condition could evaluate differently when subsequently #included. Reject + // this. + if (DidMacroExpansion) + return Invalidate(); + + // Remember that we're in the #if and that we have the macro. + ReadAnyTokens = true; + TheMacro = M; + } + + /// EnterTopLevelConditional - This is invoked when a top level conditional + /// (except #ifndef) is found. + void EnterTopLevelConditional() { + /// If a conditional directive (except #ifndef) is found at the top level, + /// there is a chunk of the file not guarded by the controlling macro. + Invalidate(); + } + + /// ExitTopLevelConditional - This method is called when the lexer exits the + /// top-level conditional. + void ExitTopLevelConditional() { + // If we have a macro, that means the top of the file was ok. Set our state + // back to "not having read any tokens" so we can detect anything after the + // #endif. + if (!TheMacro) return Invalidate(); + + // At this point, we haven't "read any tokens" but we do have a controlling + // macro. + ReadAnyTokens = false; + } + + /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if + /// there is a controlling macro, return it. + const IdentifierInfo *GetControllingMacroAtEndOfFile() const { + // If we haven't read any tokens after the #endif, return the controlling + // macro if it's valid (if it isn't, it will be null). + if (!ReadAnyTokens) + return TheMacro; + return 0; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h new file mode 100644 index 0000000..d74124e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h @@ -0,0 +1,148 @@ +//===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- 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 PPCallbacks interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H +#define LLVM_CLANG_LEX_PPCALLBACKS_H + +#include "clang/Lex/DirectoryLookup.h" +#include "clang/Basic/SourceLocation.h" +#include <string> + +namespace clang { + class SourceLocation; + class Token; + class IdentifierInfo; + class MacroInfo; + +/// PPCallbacks - This interface provides a way to observe the actions of the +/// preprocessor as it does its thing. Clients can define their hooks here to +/// implement preprocessor level tools. +class PPCallbacks { +public: + virtual ~PPCallbacks(); + + enum FileChangeReason { + EnterFile, ExitFile, SystemHeaderPragma, RenameFile + }; + + /// FileChanged - This callback is invoked whenever a source file is + /// entered or exited. The SourceLocation indicates the new location, and + /// EnteringFile indicates whether this is because we are entering a new + /// #include'd file (when true) or whether we're exiting one because we ran + /// off the end (when false). + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType) { + } + + /// FileSkipped - This callback is invoked whenever a source file is + /// skipped as the result of header guard optimization. ParentFile + /// is the file that #includes the skipped file. FilenameTok is the + /// token in ParentFile that indicates the skipped file. + virtual void FileSkipped(const FileEntry &ParentFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + } + + /// EndOfMainFile - This callback is invoked when the end of the main file is + /// reach, no subsequent callbacks will be made. + virtual void EndOfMainFile() { + } + + /// Ident - This callback is invoked when a #ident or #sccs directive is read. + /// + virtual void Ident(SourceLocation Loc, const std::string &str) { + } + + /// PragmaComment - This callback is invoked when a #pragma comment directive + /// is read. + /// + virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, + const std::string &Str) { + } + + /// MacroExpands - This is called by + /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is + /// found. + virtual void MacroExpands(const Token &Id, const MacroInfo* MI) { + } + + /// MacroDefined - This hook is called whenever a macro definition is seen. + virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) { + } + + /// MacroUndefined - This hook is called whenever a macro #undef is seen. + /// MI is released immediately following this callback. + virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) { + } +}; + +/// PPChainedCallbacks - Simple wrapper class for chaining callbacks. +class PPChainedCallbacks : public PPCallbacks { + PPCallbacks *First, *Second; + +public: + PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second) + : First(_First), Second(_Second) {} + ~PPChainedCallbacks() { + delete Second; + delete First; + } + + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType) { + First->FileChanged(Loc, Reason, FileType); + Second->FileChanged(Loc, Reason, FileType); + } + + virtual void FileSkipped(const FileEntry &ParentFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + First->FileSkipped(ParentFile, FilenameTok, FileType); + Second->FileSkipped(ParentFile, FilenameTok, FileType); + } + + virtual void EndOfMainFile() { + First->EndOfMainFile(); + Second->EndOfMainFile(); + } + + virtual void Ident(SourceLocation Loc, const std::string &str) { + First->Ident(Loc, str); + Second->Ident(Loc, str); + } + + virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, + const std::string &Str) { + First->PragmaComment(Loc, Kind, Str); + Second->PragmaComment(Loc, Kind, Str); + } + + virtual void MacroExpands(const Token &Id, const MacroInfo* MI) { + First->MacroExpands(Id, MI); + Second->MacroExpands(Id, MI); + } + + virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) { + First->MacroDefined(II, MI); + Second->MacroDefined(II, MI); + } + + virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) { + First->MacroUndefined(II, MI); + Second->MacroUndefined(II, MI); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h new file mode 100644 index 0000000..e96a8c5 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h @@ -0,0 +1,104 @@ +//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- 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 PTHLexer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PTHLEXER_H +#define LLVM_CLANG_PTHLEXER_H + +#include "clang/Lex/PreprocessorLexer.h" +#include <vector> + +namespace clang { + +class PTHManager; +class PTHSpellingSearch; + +class PTHLexer : public PreprocessorLexer { + SourceLocation FileStartLoc; + + /// TokBuf - Buffer from PTH file containing raw token data. + const unsigned char* TokBuf; + + /// CurPtr - Pointer into current offset of the token buffer where + /// the next token will be read. + const unsigned char* CurPtr; + + /// LastHashTokPtr - Pointer into TokBuf of the last processed '#' + /// token that appears at the start of a line. + const unsigned char* LastHashTokPtr; + + /// PPCond - Pointer to a side table in the PTH file that provides a + /// a consise summary of the preproccessor conditional block structure. + /// This is used to perform quick skipping of conditional blocks. + const unsigned char* PPCond; + + /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry + /// to process when doing quick skipping of preprocessor blocks. + const unsigned char* CurPPCondPtr; + + PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT + void operator=(const PTHLexer&); // DO NOT IMPLEMENT + + /// ReadToken - Used by PTHLexer to read tokens TokBuf. + void ReadToken(Token& T); + + /// PTHMgr - The PTHManager object that created this PTHLexer. + PTHManager& PTHMgr; + + Token EofToken; + +protected: + friend class PTHManager; + + /// Create a PTHLexer for the specified token stream. + PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D, + const unsigned char* ppcond, PTHManager &PM); +public: + + ~PTHLexer() {} + + /// Lex - Return the next token. + void Lex(Token &Tok); + + void getEOF(Token &Tok); + + /// DiscardToEndOfLine - Read the rest of the current preprocessor line as an + /// uninterpreted string. This switches the lexer out of directive mode. + void DiscardToEndOfLine(); + + /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a + /// tok::l_paren token, 0 if it is something else and 2 if there are no more + /// tokens controlled by this lexer. + unsigned isNextPPTokenLParen() { + // isNextPPTokenLParen is not on the hot path, and all we care about is + // whether or not we are at a token with kind tok::eof or tok::l_paren. + // Just read the first byte from the current token pointer to determine + // its kind. + tok::TokenKind x = (tok::TokenKind)*CurPtr; + return x == tok::eof ? 2 : x == tok::l_paren; + } + + /// IndirectLex - An indirect call to 'Lex' that can be invoked via + /// the PreprocessorLexer interface. + void IndirectLex(Token &Result) { Lex(Result); } + + /// getSourceLocation - Return a source location for the token in + /// the current file. + SourceLocation getSourceLocation(); + + /// SkipBlock - Used by Preprocessor to skip the current conditional block. + bool SkipBlock(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h new file mode 100644 index 0000000..5e8a4f1 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h @@ -0,0 +1,140 @@ +//===--- PTHManager.h - Manager object for PTH processing -------*- 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 PTHManager interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PTHMANAGER_H +#define LLVM_CLANG_PTHMANAGER_H + +#include "clang/Lex/PTHLexer.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" +#include <string> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class FileEntry; +class PTHLexer; +class Diagnostic; +class StatSysCallCache; + +class PTHManager : public IdentifierInfoLookup { + friend class PTHLexer; + + /// The memory mapped PTH file. + const llvm::MemoryBuffer* Buf; + + /// Alloc - Allocator used for IdentifierInfo objects. + llvm::BumpPtrAllocator Alloc; + + /// IdMap - A lazily generated cache mapping from persistent identifiers to + /// IdentifierInfo*. + IdentifierInfo** PerIDCache; + + /// FileLookup - Abstract data structure used for mapping between files + /// and token data in the PTH file. + void* FileLookup; + + /// IdDataTable - Array representing the mapping from persistent IDs to the + /// data offset within the PTH file containing the information to + /// reconsitute an IdentifierInfo. + const unsigned char* const IdDataTable; + + /// SortedIdTable - Abstract data structure mapping from strings to + /// persistent IDs. This is used by get(). + void* StringIdLookup; + + /// NumIds - The number of identifiers in the PTH file. + const unsigned NumIds; + + /// PP - The Preprocessor object that will use this PTHManager to create + /// PTHLexer objects. + Preprocessor* PP; + + /// SpellingBase - The base offset within the PTH memory buffer that + /// contains the cached spellings for literals. + const unsigned char* const SpellingBase; + + /// OriginalSourceFile - A null-terminated C-string that specifies the name + /// if the file (if any) that was to used to generate the PTH cache. + const char* OriginalSourceFile; + + /// This constructor is intended to only be called by the static 'Create' + /// method. + PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, + const unsigned char* idDataTable, IdentifierInfo** perIDCache, + void* stringIdLookup, unsigned numIds, + const unsigned char* spellingBase, const char *originalSourceFile); + + // Do not implement. + PTHManager(); + void operator=(const PTHManager&); + + /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached + /// spelling for a token. + unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer); + + /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the + /// PTH file. + inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) { + // Check if the IdentifierInfo has already been resolved. + if (IdentifierInfo* II = PerIDCache[PersistentID]) + return II; + return LazilyCreateIdentifierInfo(PersistentID); + } + IdentifierInfo* LazilyCreateIdentifierInfo(unsigned PersistentID); + +public: + // The current PTH version. + enum { Version = 9 }; + + ~PTHManager(); + + /// getOriginalSourceFile - Return the full path to the original header + /// file name that was used to generate the PTH cache. + const char* getOriginalSourceFile() const { + return OriginalSourceFile; + } + + /// get - Return the identifier token info for the specified named identifier. + /// Unlike the version in IdentifierTable, this returns a pointer instead + /// of a reference. If the pointer is NULL then the IdentifierInfo cannot + /// be found. + IdentifierInfo *get(llvm::StringRef Name); + + /// Create - This method creates PTHManager objects. The 'file' argument + /// is the name of the PTH file. This method returns NULL upon failure. + static PTHManager *Create(const std::string& file, Diagnostic &Diags); + + void setPreprocessor(Preprocessor *pp) { PP = pp; } + + /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the + /// specified file. This method returns NULL if no cached tokens exist. + /// It is the responsibility of the caller to 'delete' the returned object. + PTHLexer *CreateLexer(FileID FID); + + /// createStatCache - Returns a StatSysCallCache object for use with + /// FileManager objects. These objects use the PTH data to speed up + /// calls to stat by memoizing their results from when the PTH file + /// was generated. + StatSysCallCache *createStatCache(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h new file mode 100644 index 0000000..ef367fe --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h @@ -0,0 +1,90 @@ +//===--- Pragma.h - Pragma registration and handling ------------*- 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 PragmaHandler and PragmaTable interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PRAGMA_H +#define LLVM_CLANG_PRAGMA_H + +#include <cassert> +#include <vector> + +namespace clang { + class Preprocessor; + class Token; + class IdentifierInfo; + class PragmaNamespace; + +/// PragmaHandler - Instances of this interface defined to handle the various +/// pragmas that the language front-end uses. Each handler optionally has a +/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with +/// that identifier is found. If a handler does not match any of the declared +/// pragmas the handler with a null identifier is invoked, if it exists. +/// +/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g. +/// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other +/// pragmas. +class PragmaHandler { + const IdentifierInfo *Name; +public: + PragmaHandler(const IdentifierInfo *name) : Name(name) {} + virtual ~PragmaHandler(); + + const IdentifierInfo *getName() const { return Name; } + virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0; + + /// getIfNamespace - If this is a namespace, return it. This is equivalent to + /// using a dynamic_cast, but doesn't require RTTI. + virtual PragmaNamespace *getIfNamespace() { return 0; } +}; + +/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, +/// allowing hierarchical pragmas to be defined. Common examples of namespaces +/// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may +/// be (potentially recursively) defined. +class PragmaNamespace : public PragmaHandler { + /// Handlers - This is the list of handlers in this namespace. + /// + std::vector<PragmaHandler*> Handlers; +public: + PragmaNamespace(const IdentifierInfo *Name) : PragmaHandler(Name) {} + virtual ~PragmaNamespace(); + + /// FindHandler - Check to see if there is already a handler for the + /// specified name. If not, return the handler for the null identifier if it + /// exists, otherwise return null. If IgnoreNull is true (the default) then + /// the null handler isn't returned on failure to match. + PragmaHandler *FindHandler(const IdentifierInfo *Name, + bool IgnoreNull = true) const; + + /// AddPragma - Add a pragma to this namespace. + /// + void AddPragma(PragmaHandler *Handler) { + Handlers.push_back(Handler); + } + + /// RemovePragmaHandler - Remove the given handler from the + /// namespace. + void RemovePragmaHandler(PragmaHandler *Handler); + + bool IsEmpty() { + return Handlers.empty(); + } + + virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + + virtual PragmaNamespace *getIfNamespace() { return this; } +}; + + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h new file mode 100644 index 0000000..ef28af9 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h @@ -0,0 +1,274 @@ +//===--- PreprocessingRecord.h - Record of Preprocessing --------*- 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 PreprocessingRecord class, which maintains a record +// of what occurred during preprocessing. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H +#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H + +#include "clang/Lex/PPCallbacks.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace clang { + class IdentifierInfo; + class PreprocessingRecord; +} + +/// \brief Allocates memory within a Clang preprocessing record. +void* operator new(size_t bytes, clang::PreprocessingRecord& PR, + unsigned alignment = 8) throw(); + +/// \brief Frees memory allocated in a Clang preprocessing record. +void operator delete(void* ptr, clang::PreprocessingRecord& PR, + unsigned) throw(); + +namespace clang { + class MacroDefinition; + + /// \brief Base class that describes a preprocessed entity, which may be a + /// preprocessor directive or macro instantiation. + class PreprocessedEntity { + public: + /// \brief The kind of preprocessed entity an object describes. + enum EntityKind { + /// \brief A macro instantiation. + MacroInstantiationKind, + + /// \brief A preprocessing directive whose kind is not specified. + /// + /// This kind will be used for any preprocessing directive that does not + /// have a more specific kind within the \c DirectiveKind enumeration. + PreprocessingDirectiveKind, + + /// \brief A macro definition. + MacroDefinitionKind, + + FirstPreprocessingDirective = PreprocessingDirectiveKind, + LastPreprocessingDirective = MacroDefinitionKind + }; + + private: + /// \brief The kind of preprocessed entity that this object describes. + EntityKind Kind; + + /// \brief The source range that covers this preprocessed entity. + SourceRange Range; + + protected: + PreprocessedEntity(EntityKind Kind, SourceRange Range) + : Kind(Kind), Range(Range) { } + + public: + /// \brief Retrieve the kind of preprocessed entity stored in this object. + EntityKind getKind() const { return Kind; } + + /// \brief Retrieve the source range that covers this entire preprocessed + /// entity. + SourceRange getSourceRange() const { return Range; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const PreprocessedEntity *) { return true; } + + // Only allow allocation of preprocessed entities using the allocator + // in PreprocessingRecord or by doing a placement new. + void* operator new(size_t bytes, PreprocessingRecord& PR, + unsigned alignment = 8) throw() { + return ::operator new(bytes, PR, alignment); + } + + void* operator new(size_t bytes, void* mem) throw() { + return mem; + } + + void operator delete(void* ptr, PreprocessingRecord& PR, + unsigned alignment) throw() { + return ::operator delete(ptr, PR, alignment); + } + + void operator delete(void*, std::size_t) throw() { } + void operator delete(void*, void*) throw() { } + + private: + // Make vanilla 'new' and 'delete' illegal for preprocessed entities. + void* operator new(size_t bytes) throw(); + void operator delete(void* data) throw(); + }; + + /// \brief Records the location of a macro instantiation. + class MacroInstantiation : public PreprocessedEntity { + /// \brief The name of the macro being instantiation. + IdentifierInfo *Name; + + /// \brief The definition of this macro. + MacroDefinition *Definition; + + public: + MacroInstantiation(IdentifierInfo *Name, SourceRange Range, + MacroDefinition *Definition) + : PreprocessedEntity(MacroInstantiationKind, Range), Name(Name), + Definition(Definition) { } + + /// \brief The name of the macro being instantiated. + IdentifierInfo *getName() const { return Name; } + + /// \brief The definition of the macro being instantiated. + MacroDefinition *getDefinition() const { return Definition; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const PreprocessedEntity *PE) { + return PE->getKind() == MacroInstantiationKind; + } + static bool classof(const MacroInstantiation *) { return true; } + + }; + + /// \brief Records the presence of a preprocessor directive. + class PreprocessingDirective : public PreprocessedEntity { + public: + PreprocessingDirective(EntityKind Kind, SourceRange Range) + : PreprocessedEntity(Kind, Range) { } + + // Implement isa/cast/dyncast/etc. + static bool classof(const PreprocessedEntity *PD) { + return PD->getKind() >= FirstPreprocessingDirective && + PD->getKind() <= LastPreprocessingDirective; + } + static bool classof(const PreprocessingDirective *) { return true; } + }; + + /// \brief Record the location of a macro definition. + class MacroDefinition : public PreprocessingDirective { + /// \brief The name of the macro being defined. + const IdentifierInfo *Name; + + /// \brief The location of the macro name in the macro definition. + SourceLocation Location; + + public: + explicit MacroDefinition(const IdentifierInfo *Name, SourceLocation Location, + SourceRange Range) + : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name), + Location(Location) { } + + /// \brief Retrieve the name of the macro being defined. + const IdentifierInfo *getName() const { return Name; } + + /// \brief Retrieve the location of the macro name in the definition. + SourceLocation getLocation() const { return Location; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const PreprocessedEntity *PE) { + return PE->getKind() == MacroDefinitionKind; + } + static bool classof(const MacroDefinition *) { return true; } + }; + + /// \brief An abstract class that should be subclassed by any external source + /// of preprocessing record entries. + class ExternalPreprocessingRecordSource { + public: + virtual ~ExternalPreprocessingRecordSource(); + + /// \brief Read any preallocated preprocessed entities from the external + /// source. + virtual void ReadPreprocessedEntities() = 0; + }; + + /// \brief A record of the steps taken while preprocessing a source file, + /// including the various preprocessing directives processed, macros + /// instantiated, etc. + class PreprocessingRecord : public PPCallbacks { + /// \brief Allocator used to store preprocessing objects. + llvm::BumpPtrAllocator BumpAlloc; + + /// \brief The set of preprocessed entities in this record, in order they + /// were seen. + std::vector<PreprocessedEntity *> PreprocessedEntities; + + /// \brief Mapping from MacroInfo structures to their definitions. + llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions; + + /// \brief External source of preprocessed entities. + ExternalPreprocessingRecordSource *ExternalSource; + + /// \brief The number of preallocated entities (that are known to the + /// external source). + unsigned NumPreallocatedEntities; + + /// \brief Whether we have already loaded all of the preallocated entities. + mutable bool LoadedPreallocatedEntities; + + void MaybeLoadPreallocatedEntities() const ; + + public: + PreprocessingRecord(); + + /// \brief Allocate memory in the preprocessing record. + void *Allocate(unsigned Size, unsigned Align = 8) { + return BumpAlloc.Allocate(Size, Align); + } + + /// \brief Deallocate memory in the preprocessing record. + void Deallocate(void *Ptr) { } + + // Iteration over the preprocessed entities. + typedef std::vector<PreprocessedEntity *>::iterator iterator; + typedef std::vector<PreprocessedEntity *>::const_iterator const_iterator; + iterator begin(bool OnlyLocalEntities = false); + iterator end(bool OnlyLocalEntities = false); + const_iterator begin(bool OnlyLocalEntities = false) const; + const_iterator end(bool OnlyLocalEntities = false) const; + + /// \brief Add a new preprocessed entity to this record. + void addPreprocessedEntity(PreprocessedEntity *Entity); + + /// \brief Set the external source for preprocessed entities. + void SetExternalSource(ExternalPreprocessingRecordSource &Source, + unsigned NumPreallocatedEntities); + + /// \brief Set the preallocated entry at the given index to the given + /// preprocessed entity. + void SetPreallocatedEntity(unsigned Index, PreprocessedEntity *Entity); + + /// \brief Register a new macro definition. + void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *MD); + + /// \brief Retrieve the preprocessed entity at the given index. + PreprocessedEntity *getPreprocessedEntity(unsigned Index) { + assert(Index < PreprocessedEntities.size() && + "Out-of-bounds preprocessed entity"); + return PreprocessedEntities[Index]; + } + + /// \brief Retrieve the macro definition that corresponds to the given + /// \c MacroInfo. + MacroDefinition *findMacroDefinition(const MacroInfo *MI); + + virtual void MacroExpands(const Token &Id, const MacroInfo* MI); + virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI); + virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI); + }; +} // end namespace clang + +inline void* operator new(size_t bytes, clang::PreprocessingRecord& PR, + unsigned alignment) throw() { + return PR.Allocate(bytes, alignment); +} + +inline void operator delete(void* ptr, clang::PreprocessingRecord& PR, + unsigned) throw() { + PR.Deallocate(ptr); +} + +#endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h new file mode 100644 index 0000000..f01b3af --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -0,0 +1,939 @@ +//===--- Preprocessor.h - C Language Family Preprocessor --------*- 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 Preprocessor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H +#define LLVM_CLANG_LEX_PREPROCESSOR_H + +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/TokenLexer.h" +#include "clang/Lex/PTHManager.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace clang { + +class SourceManager; +class ExternalPreprocessorSource; +class FileManager; +class FileEntry; +class HeaderSearch; +class PragmaNamespace; +class PragmaHandler; +class CommentHandler; +class ScratchBuffer; +class TargetInfo; +class PPCallbacks; +class DirectoryLookup; +class PreprocessingRecord; + +/// 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 { + Diagnostic *Diags; + LangOptions Features; + const TargetInfo &Target; + FileManager &FileMgr; + SourceManager &SourceMgr; + ScratchBuffer *ScratchBuf; + HeaderSearch &HeaderInfo; + + /// \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; + + /// BP - A BumpPtrAllocator object used to quickly allocate and release + /// objects internal to the Preprocessor. + llvm::BumpPtrAllocator BP; + + /// Identifiers for builtin macros and other builtins. + IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__ + IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__ + IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__ + IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__ + IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__ + IdentifierInfo *Ident__COUNTER__; // __COUNTER__ + IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__ + IdentifierInfo *Ident__has_feature; // __has_feature + IdentifierInfo *Ident__has_builtin; // __has_builtin + IdentifierInfo *Ident__has_include; // __has_include + IdentifierInfo *Ident__has_include_next; // __has_include_next + + SourceLocation DATELoc, TIMELoc; + unsigned CounterValue; // Next __COUNTER__ value. + + enum { + /// MaxIncludeStackDepth - Maximum depth of #includes. + MaxAllowedIncludeStackDepth = 200 + }; + + // State that is set before the preprocessor begins. + bool KeepComments : 1; + bool KeepMacroComments : 1; + + // State that changes while the preprocessor runs: + bool InMacroArgs : 1; // True if parsing fn macro invocation args. + + /// Whether the preprocessor owns the header search object. + bool OwnsHeaderSearch : 1; + + /// DisableMacroExpansion - True if macro expansion is disabled. + bool DisableMacroExpansion : 1; + + /// \brief Whether we have already loaded macros from the external source. + mutable bool ReadMacrosFromExternalSource : 1; + + /// Identifiers - This is mapping/lookup information for all identifiers in + /// the program, including program keywords. + mutable IdentifierTable Identifiers; + + /// Selectors - This table contains all the selectors in the program. Unlike + /// IdentifierTable above, this table *isn't* populated by the preprocessor. + /// It is declared/instantiated here because it's role/lifetime is + /// conceptually similar the IdentifierTable. In addition, the current control + /// flow (in clang::ParseAST()), make it convenient to put here. + /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to + /// the lifetime fo the preprocessor. + SelectorTable Selectors; + + /// BuiltinInfo - Information about builtins. + Builtin::Context BuiltinInfo; + + /// PragmaHandlers - This tracks all of the pragmas that the client registered + /// with this preprocessor. + PragmaNamespace *PragmaHandlers; + + /// \brief Tracks all of the comment handlers that the client registered + /// with this preprocessor. + std::vector<CommentHandler *> CommentHandlers; + + /// \brief The file that we're performing code-completion for, if any. + const FileEntry *CodeCompletionFile; + + /// 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; + + /// 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; + + /// 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. + const DirectoryLookup *CurDirLookup; + + /// 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; + + /// IncludeMacroStack - This keeps track of the stack of files currently + /// #included, and macros currently being expanded from, not counting + /// CurLexer/CurTokenLexer. + struct IncludeStackInfo { + Lexer *TheLexer; + PTHLexer *ThePTHLexer; + PreprocessorLexer *ThePPLexer; + TokenLexer *TheTokenLexer; + const DirectoryLookup *TheDirLookup; + + IncludeStackInfo(Lexer *L, PTHLexer* P, PreprocessorLexer* PPL, + TokenLexer* TL, const DirectoryLookup *D) + : TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL), + TheDirLookup(D) {} + }; + std::vector<IncludeStackInfo> IncludeMacroStack; + + /// Callbacks - These are actions invoked when some preprocessor activity is + /// encountered (e.g. a file is #included, etc). + PPCallbacks *Callbacks; + + /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping + /// to the actual definition of the macro. + llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; + + /// MICache - A "freelist" of MacroInfo objects that can be reused for quick + /// allocation. + /// FIXME: why not use a singly linked list? + std::vector<MacroInfo*> MICache; + + /// MacroArgCache - This is a "freelist" of MacroArg objects that can be + /// reused for quick allocation. + MacroArgs *MacroArgCache; + friend class MacroArgs; + + // Various statistics we track for performance analysis. + unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; + unsigned NumIf, NumElse, NumEndif; + unsigned NumEnteredSourceFiles, MaxIncludeStackDepth; + unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded; + unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste; + unsigned NumSkipped; + + /// Predefines - This string is the predefined macros that preprocessor + /// should use from the command line etc. + std::string Predefines; + + /// TokenLexerCache - Cache macro expanders to reduce malloc traffic. + enum { TokenLexerCacheSize = 8 }; + unsigned NumCachedTokenLexers; + TokenLexer *TokenLexerCache[TokenLexerCacheSize]; + + /// \brief A record of the macro definitions and instantiations that + /// 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 llvm::SmallVector<Token, 1> CachedTokensTy; + + /// CachedTokens - Cached tokens are stored here when we do backtracking or + /// lookahead. They are "lexed" by the CachingLex() method. + CachedTokensTy CachedTokens; + + /// CachedLexPos - The position of the cached token that CachingLex() should + /// "lex" next. If it points beyond the CachedTokens vector, it means that + /// a normal Lex() should be invoked. + CachedTokensTy::size_type CachedLexPos; + + /// BacktrackPositions - Stack of backtrack positions, allowing nested + /// backtracks. The EnableBacktrackAtThisPos() method pushes a position to + /// indicate where CachedLexPos should be set when the BackTrack() method is + /// invoked (at which point the last position is popped). + std::vector<CachedTokensTy::size_type> BacktrackPositions; + +public: + Preprocessor(Diagnostic &diags, const LangOptions &opts, + const TargetInfo &target, + SourceManager &SM, HeaderSearch &Headers, + IdentifierInfoLookup *IILookup = 0, + bool OwnsHeaderSearch = false); + + ~Preprocessor(); + + Diagnostic &getDiagnostics() const { return *Diags; } + void setDiagnostics(Diagnostic &D) { Diags = &D; } + + const LangOptions &getLangOptions() const { return Features; } + const TargetInfo &getTargetInfo() const { return Target; } + FileManager &getFileManager() const { return FileMgr; } + SourceManager &getSourceManager() const { return SourceMgr; } + HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; } + + IdentifierTable &getIdentifierTable() { return Identifiers; } + SelectorTable &getSelectorTable() { return Selectors; } + Builtin::Context &getBuiltinInfo() { return BuiltinInfo; } + llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; } + + void setPTHManager(PTHManager* pm); + + PTHManager *getPTHManager() { return PTH.get(); } + + void setExternalSource(ExternalPreprocessorSource *Source) { + ExternalSource = Source; + } + + ExternalPreprocessorSource *getExternalSource() const { + return ExternalSource; + } + + /// SetCommentRetentionState - Control whether or not the preprocessor retains + /// comments in output. + void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { + this->KeepComments = KeepComments | KeepMacroComments; + this->KeepMacroComments = KeepMacroComments; + } + + bool getCommentRetentionState() const { return KeepComments; } + + /// isCurrentLexer - Return true if we are lexing directly from the specified + /// lexer. + bool isCurrentLexer(const PreprocessorLexer *L) const { + return CurPPLexer == L; + } + + /// getCurrentLexer - Return the current lexer being lexed from. Note + /// that this ignores any potentially active macro expansions and _Pragma + /// expansions going on at the time. + PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; } + + /// getCurrentFileLexer - Return the current file lexer being lexed from. + /// Note that this ignores any potentially active macro expansions and _Pragma + /// expansions going on at the time. + PreprocessorLexer *getCurrentFileLexer() const; + + /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks. + /// Note that this class takes ownership of any PPCallbacks object given to + /// it. + PPCallbacks *getPPCallbacks() const { return Callbacks; } + void addPPCallbacks(PPCallbacks *C) { + if (Callbacks) + C = new PPChainedCallbacks(C, Callbacks); + Callbacks = C; + } + + /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to + /// or null if it isn't #define'd. + MacroInfo *getMacroInfo(IdentifierInfo *II) const { + return II->hasMacroDefinition() ? Macros.find(II)->second : 0; + } + + /// setMacroInfo - Specify a macro for this identifier. + /// + void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); + + /// macro_iterator/macro_begin/macro_end - This allows you to walk the current + /// state of the macro table. This visits every currently-defined macro. + typedef llvm::DenseMap<IdentifierInfo*, + MacroInfo*>::const_iterator macro_iterator; + macro_iterator macro_begin(bool IncludeExternalMacros = true) const; + macro_iterator macro_end(bool IncludeExternalMacros = true) const; + + const std::string &getPredefines() const { return Predefines; } + /// setPredefines - Set the predefines for this Preprocessor. These + /// predefines are automatically injected when parsing the main file. + void setPredefines(const char *P) { Predefines = P; } + void setPredefines(const std::string &P) { Predefines = P; } + + /// getIdentifierInfo - Return information about the specified preprocessor + /// identifier token. The version of this method that takes two character + /// pointers is preferred unless the identifier is already available as a + /// string (this avoids allocation and copying of memory to construct an + /// std::string). + IdentifierInfo *getIdentifierInfo(llvm::StringRef Name) const { + return &Identifiers.get(Name); + } + + /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. + /// If 'Namespace' is non-null, then it is a token required to exist on the + /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". + void AddPragmaHandler(const char *Namespace, PragmaHandler *Handler); + + /// RemovePragmaHandler - Remove the specific pragma handler from + /// the preprocessor. If \arg Namespace is non-null, then it should + /// be the namespace that \arg Handler was added to. It is an error + /// to remove a handler that has not been registered. + void RemovePragmaHandler(const char *Namespace, PragmaHandler *Handler); + + /// \brief Add the specified comment handler to the preprocessor. + void AddCommentHandler(CommentHandler *Handler); + + /// \brief Remove the specified comment handler. + /// + /// It is an error to remove a handler that has not been registered. + void RemoveCommentHandler(CommentHandler *Handler); + + /// \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 + /// all macro expansions, macro definitions, etc. + void createPreprocessingRecord(); + + /// EnterMainSourceFile - Enter the specified FileID as the main source file, + /// which implicitly adds the builtin defines etc. + void EnterMainSourceFile(); + + /// EndSourceFile - Inform the preprocessor callbacks that processing is + /// complete. + void EndSourceFile(); + + /// EnterSourceFile - Add a source file to the top of the include stack and + /// start lexing tokens from it instead of the current buffer. Emit an error + /// and don't enter the file on error. + void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, + SourceLocation Loc); + + /// EnterMacro - Add a Macro to the top of the include stack and start lexing + /// tokens from it instead of the current buffer. Args specifies the + /// tokens input to a function-like macro. + /// + /// ILEnd specifies the location of the ')' for a function-like macro or the + /// identifier for an object-like macro. + void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args); + + /// EnterTokenStream - Add a "macro" context to the top of the include stack, + /// which will cause the lexer to start returning the specified tokens. + /// + /// If DisableMacroExpansion is true, tokens lexed from the token stream will + /// not be subject to further macro expansion. Otherwise, these tokens will + /// be re-macro-expanded when/if expansion is enabled. + /// + /// If OwnsTokens is false, this method assumes that the specified stream of + /// tokens has a permanent owner somewhere, so they do not need to be copied. + /// If it is true, it assumes the array of tokens is allocated with new[] and + /// must be freed. + /// + void EnterTokenStream(const Token *Toks, unsigned NumToks, + bool DisableMacroExpansion, bool OwnsTokens); + + /// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the + /// lexer stack. This should only be used in situations where the current + /// state of the top-of-stack lexer is known. + void RemoveTopOfLexerStack(); + + /// EnableBacktrackAtThisPos - From the point that this method is called, and + /// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor + /// keeps track of the lexed tokens so that a subsequent Backtrack() call will + /// make the Preprocessor re-lex the same tokens. + /// + /// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can + /// be called multiple times and CommitBacktrackedTokens/Backtrack calls will + /// be combined with the EnableBacktrackAtThisPos calls in reverse order. + /// + /// NOTE: *DO NOT* forget to call either CommitBacktrackedTokens or Backtrack + /// at some point after EnableBacktrackAtThisPos. If you don't, caching of + /// tokens will continue indefinitely. + /// + void EnableBacktrackAtThisPos(); + + /// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call. + void CommitBacktrackedTokens(); + + /// Backtrack - Make Preprocessor re-lex the tokens that were lexed since + /// EnableBacktrackAtThisPos() was previously called. + void Backtrack(); + + /// isBacktrackEnabled - True if EnableBacktrackAtThisPos() was called and + /// caching of tokens is on. + bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } + + /// Lex - To lex a token from the preprocessor, just pull a token from the + /// current lexer or macro object. + void Lex(Token &Result) { + if (CurLexer) + CurLexer->Lex(Result); + else if (CurPTHLexer) + CurPTHLexer->Lex(Result); + else if (CurTokenLexer) + CurTokenLexer->Lex(Result); + else + CachingLex(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. + void LexNonComment(Token &Result) { + do + Lex(Result); + while (Result.getKind() == tok::comment); + } + + /// LexUnexpandedToken - This is just like Lex, but this disables macro + /// expansion of identifier tokens. + void LexUnexpandedToken(Token &Result) { + // Disable macro expansion. + bool OldVal = DisableMacroExpansion; + DisableMacroExpansion = true; + // Lex the token. + Lex(Result); + + // Reenable it. + DisableMacroExpansion = OldVal; + } + + /// LookAhead - This peeks ahead N tokens and returns that token without + /// consuming any tokens. LookAhead(0) returns the next token that would be + /// returned by Lex(), LookAhead(1) returns the token after it, etc. This + /// returns normal tokens after phase 5. As such, it is equivalent to using + /// 'Lex', not 'LexUnexpandedToken'. + const Token &LookAhead(unsigned N) { + if (CachedLexPos + N < CachedTokens.size()) + return CachedTokens[CachedLexPos+N]; + else + return PeekAhead(N+1); + } + + /// RevertCachedTokens - When backtracking is enabled and tokens are cached, + /// this allows to revert a specific number of tokens. + /// Note that the number of tokens being reverted should be up to the last + /// backtrack position, not more. + void RevertCachedTokens(unsigned N) { + assert(isBacktrackEnabled() && + "Should only be called when tokens are cached for backtracking"); + assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) + && "Should revert tokens up to the last backtrack position, not more"); + assert(signed(CachedLexPos) - signed(N) >= 0 && + "Corrupted backtrack positions ?"); + CachedLexPos -= N; + } + + /// EnterToken - Enters a token in the token stream to be lexed next. If + /// BackTrack() is called afterwards, the token will remain at the insertion + /// point. + void EnterToken(const Token &Tok) { + EnterCachingLexMode(); + CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Tok); + } + + /// AnnotateCachedTokens - We notify the Preprocessor that if it is caching + /// tokens (because backtrack is enabled) it should replace the most recent + /// cached tokens with the given annotation token. This function has no effect + /// if backtracking is not enabled. + /// + /// Note that the use of this function is just for optimization; so that the + /// cached tokens doesn't get re-parsed and re-resolved after a backtrack is + /// invoked. + void AnnotateCachedTokens(const Token &Tok) { + assert(Tok.isAnnotation() && "Expected annotation token"); + if (CachedLexPos != 0 && isBacktrackEnabled()) + AnnotatePreviousCachedTokens(Tok); + } + + /// \brief Replace the last token with an annotation token. + /// + /// Like AnnotateCachedTokens(), this routine replaces an + /// already-parsed (and resolved) token with an annotation + /// token. However, this routine only replaces the last token with + /// the annotation token; it does not affect any other cached + /// tokens. This function has no effect if backtracking is not + /// enabled. + void ReplaceLastTokenWithAnnotation(const Token &Tok) { + assert(Tok.isAnnotation() && "Expected annotation token"); + if (CachedLexPos != 0 && isBacktrackEnabled()) + CachedTokens[CachedLexPos-1] = Tok; + } + + /// \brief Specify the point at which code-completion will be performed. + /// + /// \param File the file in which code completion should occur. If + /// this file is included multiple times, code-completion will + /// perform completion the first time it is included. If NULL, this + /// function clears out the code-completion point. + /// + /// \param Line the line at which code completion should occur + /// (1-based). + /// + /// \param Column the column at which code completion should occur + /// (1-based). + /// + /// \returns true if an error occurred, false otherwise. + bool SetCodeCompletionPoint(const FileEntry *File, + unsigned Line, unsigned Column); + + /// \brief Determine if this source location refers into the file + /// for which we are performing code completion. + bool isCodeCompletionFile(SourceLocation FileLoc) const; + + /// 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. + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID); + } + + DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) { + return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()), + DiagID); + } + + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a + /// token is the characters used to represent the token in the source file + /// after trigraph expansion and escaped-newline folding. In particular, this + /// wants to get the true, uncanonicalized, spelling of things like digraphs + /// UCNs, etc. + /// + /// \param Invalid If non-NULL, will be set \c true if an error occurs. + std::string getSpelling(const Token &Tok, bool *Invalid = 0) const; + + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a + /// token is the characters used to represent the token in the source file + /// after trigraph expansion and escaped-newline folding. In particular, this + /// wants to get the true, uncanonicalized, spelling of things like digraphs + /// UCNs, etc. + static std::string getSpelling(const Token &Tok, + const SourceManager &SourceMgr, + const LangOptions &Features, + bool *Invalid = 0); + + /// getSpelling - This method is used to get the spelling of a token into a + /// preallocated buffer, instead of as an std::string. The caller is required + /// to allocate enough space for the token, which is guaranteed to be at least + /// Tok.getLength() bytes long. The length of the actual result is returned. + /// + /// Note that this method may do two possible things: it may either fill in + /// the buffer specified with characters, or it may *change the input pointer* + /// 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, + bool *Invalid = 0) const; + + /// getSpelling - This method is used to get the spelling of a token into a + /// SmallVector. Note that the returned StringRef may not point to the + /// supplied buffer if a copy can be avoided. + llvm::StringRef getSpelling(const Token &Tok, + llvm::SmallVectorImpl<char> &Buffer, + bool *Invalid = 0) const; + + /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant + /// with length 1, return the character. + char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, + bool *Invalid = 0) const { + assert(Tok.is(tok::numeric_constant) && + Tok.getLength() == 1 && "Called on unsupported token"); + assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1"); + + // If the token is carrying a literal data pointer, just use it. + if (const char *D = Tok.getLiteralData()) + return *D; + + // Otherwise, fall back on getCharacterData, which is slower, but always + // works. + return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid); + } + + /// 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 instantiation point of the token. + void CreateString(const char *Buf, unsigned Len, + Token &Tok, SourceLocation SourceLoc = SourceLocation()); + + /// \brief Computes the source location just past the end of the + /// token at this source location. + /// + /// This routine can be used to produce a source location that + /// points just past the end of the token referenced by \p Loc, and + /// is generally used when a diagnostic needs to point just after a + /// token where it expected something different that it received. If + /// the returned source location would not be meaningful (e.g., if + /// it points into a macro), this routine returns an invalid + /// source location. + /// + /// \param Offset an offset from the end of the token, where the source + /// location should refer to. The default offset (0) produces a source + /// 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); + + /// DumpToken - Print the token to stderr, used for debugging. + /// + void DumpToken(const Token &Tok, bool DumpFlags = false) const; + void DumpLocation(SourceLocation Loc) const; + void DumpMacro(const MacroInfo &MI) const; + + /// AdvanceToTokenCharacter - Given a location that specifies the start of a + /// token, return a new location that specifies a character within the token. + SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,unsigned Char); + + /// IncrementPasteCounter - Increment the counters for the number of token + /// paste operations performed. If fast was specified, this is a 'fast paste' + /// case we handled. + /// + void IncrementPasteCounter(bool isFast) { + if (isFast) + ++NumFastTokenPaste; + else + ++NumTokenPaste; + } + + void PrintStats(); + + /// HandleMicrosoftCommentPaste - When the macro expander pastes together a + /// comment (/##/) in microsoft mode, this method handles updating the current + /// state, returning the token on the next source line. + void HandleMicrosoftCommentPaste(Token &Tok); + + //===--------------------------------------------------------------------===// + // Preprocessor callback methods. These are invoked by a lexer as various + // directives and events are found. + + /// LookUpIdentifierInfo - Given a tok::identifier token, look up the + /// identifier information for the token and install it into the token. + IdentifierInfo *LookUpIdentifierInfo(Token &Identifier, + const char *BufPtr = 0) const; + + /// HandleIdentifier - This callback is invoked when the lexer reads an + /// identifier and has filled in the tokens IdentifierInfo member. This + /// callback potentially macro expands it or turns it into a named token (like + /// 'for'). + void HandleIdentifier(Token &Identifier); + + + /// HandleEndOfFile - This callback is invoked when the lexer hits the end of + /// the current file. This either returns the EOF token and returns true, or + /// pops a level off the include stack and returns false, at which point the + /// client should call lex again. + bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false); + + /// HandleEndOfTokenLexer - This callback is invoked when the current + /// TokenLexer hits the end of its token stream. + bool HandleEndOfTokenLexer(Token &Result); + + /// HandleDirective - This callback is invoked when the lexer sees a # token + /// at the start of a line. This consumes the directive, modifies the + /// lexer/preprocessor state, and advances the lexer(s) so that the next token + /// read is the correct one. + void HandleDirective(Token &Result); + + /// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If + /// not, emit a diagnostic and consume up until the eom. If EnableMacros is + /// true, then we consider macros that expand to zero tokens as being ok. + void CheckEndOfDirective(const char *Directive, bool EnableMacros = false); + + /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the + /// current line until the tok::eom token is found. + void DiscardUntilEndOfDirective(); + + /// SawDateOrTime - This returns true if the preprocessor has seen a use of + /// __DATE__ or __TIME__ in the file so far. + bool SawDateOrTime() const { + return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); + } + unsigned getCounterValue() const { return CounterValue; } + void setCounterValue(unsigned V) { CounterValue = V; } + + /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide + /// SourceLocation. + MacroInfo* AllocateMacroInfo(SourceLocation L); + + /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully + /// checked and spelled filename, e.g. as an operand of #include. This returns + /// true if the input filename was in <>'s or false if it were in ""'s. The + /// caller is expected to provide a buffer that is large enough to hold the + /// spelling of the filename, but is also expected to handle the case when + /// this method decides to use a different buffer. + bool GetIncludeFilenameSpelling(SourceLocation Loc,llvm::StringRef &Filename); + + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, + /// return null on failure. isAngled indicates whether the file reference is + /// for system #include's or not (i.e. using <> instead of ""). + const FileEntry *LookupFile(llvm::StringRef Filename, + bool isAngled, const DirectoryLookup *FromDir, + const DirectoryLookup *&CurDir); + + /// GetCurLookup - The DirectoryLookup structure used to find the current + /// FileEntry, if CurLexer is non-null and if applicable. This allows us to + /// implement #include_next and find directory-specific properties. + const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } + + /// isInPrimaryFile - Return true if we're in the top-level file, not in a + /// #include. + bool isInPrimaryFile() const; + + /// ConcatenateIncludeName - Handle cases where the #include name is expanded + /// from a macro as multiple tokens, which need to be glued together. This + /// occurs for code like: + /// #define FOO <a/b.h> + /// #include FOO + /// because in this case, "<a/b.h>" is returned as 7 tokens, not one. + /// + /// This code concatenates and consumes tokens up to the '>' token. It + /// returns false if the > was found, otherwise it returns true if it finds + /// and consumes the EOM marker. + bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer); + +private: + + void PushIncludeMacroStack() { + IncludeMacroStack.push_back(IncludeStackInfo(CurLexer.take(), + CurPTHLexer.take(), + CurPPLexer, + CurTokenLexer.take(), + CurDirLookup)); + CurPPLexer = 0; + } + + void PopIncludeMacroStack() { + CurLexer.reset(IncludeMacroStack.back().TheLexer); + CurPTHLexer.reset(IncludeMacroStack.back().ThePTHLexer); + CurPPLexer = IncludeMacroStack.back().ThePPLexer; + CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer); + CurDirLookup = IncludeMacroStack.back().TheDirLookup; + IncludeMacroStack.pop_back(); + } + + /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will + /// be reused for allocating new MacroInfo objects. + void ReleaseMacroInfo(MacroInfo* MI); + + /// ReadMacroName - Lex and validate a macro name, which occurs after a + /// #define or #undef. This emits a diagnostic, sets the token kind to eom, + /// and discards the rest of the macro line if the macro name is invalid. + void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0); + + /// 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); + + /// SkipExcludedConditionalBlock - We just read a #if or related directive and + /// decided that the subsequent tokens are in the #if'd out portion of the + /// file. Lex the rest of the file, until we see an #endif. If + /// FoundNonSkipPortion is true, then we have already emitted code for part of + /// this #if directive, so #else/#elif blocks should never be entered. If + /// FoundElse is false, then #else directives are ok, if not, then we have + /// already seen one so a #else directive is a duplicate. When this returns, + /// the caller can lex the first valid token. + void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, + bool FoundNonSkipPortion, bool FoundElse); + + /// PTHSkipExcludedConditionalBlock - A fast PTH version of + /// SkipExcludedConditionalBlock. + void PTHSkipExcludedConditionalBlock(); + + /// EvaluateDirectiveExpression - Evaluate an integer constant expression that + /// may occur after a #if or #elif directive and return it as a bool. If the + /// expression is equivalent to "!defined(X)" return X in IfNDefMacro. + bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro); + + /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas: + /// #pragma GCC poison/system_header/dependency and #pragma once. + void RegisterBuiltinPragmas(); + + /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the + /// identifier table. + void RegisterBuiltinMacros(); + + /// HandleMacroExpandedIdentifier - If an identifier token is read that is to + /// be expanded as a macro, handle it and return the next token as 'Tok'. If + /// the macro should not be expanded return true, otherwise return false. + bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI); + + /// isNextPPTokenLParen - Determine whether the next preprocessor token to be + /// lexed is a '('. If so, consume the token and return true, if not, this + /// method should have no observable side-effect on the lexed tokens. + bool isNextPPTokenLParen(); + + /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is + /// invoked to read all of the formal arguments specified for the macro + /// invocation. This returns null on error. + MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI, + SourceLocation &InstantiationEnd); + + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded + /// as a builtin macro, handle it and return the next token as 'Tok'. + void ExpandBuiltinMacro(Token &Tok); + + /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then + /// return the first token after the directive. The _Pragma token has just + /// been read into 'Tok'. + void Handle_Pragma(Token &Tok); + + /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and + /// start lexing tokens from it instead of the current buffer. + void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); + + /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and + /// start getting tokens from it using the PTH cache. + void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); + + /// IsFileLexer - Returns true if we are lexing from a file and not a + /// pragma or a macro. + static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { + return L ? !L->isPragmaLexer() : P != 0; + } + + static bool IsFileLexer(const IncludeStackInfo& I) { + return IsFileLexer(I.TheLexer, I.ThePPLexer); + } + + bool IsFileLexer() const { + return IsFileLexer(CurLexer.get(), CurPPLexer); + } + + //===--------------------------------------------------------------------===// + // Caching stuff. + void CachingLex(Token &Result); + bool InCachingLexMode() const { return CurPPLexer == 0 && CurTokenLexer == 0;} + void EnterCachingLexMode(); + void ExitCachingLexMode() { + if (InCachingLexMode()) + RemoveTopOfLexerStack(); + } + const Token &PeekAhead(unsigned N); + void AnnotatePreviousCachedTokens(const Token &Tok); + + //===--------------------------------------------------------------------===// + /// Handle*Directive - implement the various preprocessor directives. These + /// should side-effect the current preprocessor object so that the next call + /// to Lex() will return the appropriate token next. + void HandleLineDirective(Token &Tok); + void HandleDigitDirective(Token &Tok); + void HandleUserDiagnosticDirective(Token &Tok, bool isWarning); + void HandleIdentSCCSDirective(Token &Tok); + + // File inclusion. + void HandleIncludeDirective(Token &Tok, + const DirectoryLookup *LookupFrom = 0, + bool isImport = false); + void HandleIncludeNextDirective(Token &Tok); + void HandleIncludeMacrosDirective(Token &Tok); + void HandleImportDirective(Token &Tok); + + // Macro handling. + void HandleDefineDirective(Token &Tok); + void HandleUndefDirective(Token &Tok); + + // Conditional Inclusion. + void HandleIfdefDirective(Token &Tok, bool isIfndef, + bool ReadAnyTokensBeforeDirective); + void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective); + void HandleEndifDirective(Token &Tok); + void HandleElseDirective(Token &Tok); + void HandleElifDirective(Token &Tok); + + // Pragmas. + void HandlePragmaDirective(); +public: + void HandlePragmaOnce(Token &OnceTok); + void HandlePragmaMark(); + void HandlePragmaPoison(Token &PoisonTok); + void HandlePragmaSystemHeader(Token &SysHeaderTok); + void HandlePragmaDependency(Token &DependencyTok); + void HandlePragmaComment(Token &CommentTok); + // Return true and store the first token only if any CommentHandler + // has inserted some tokens and getCommentRetentionState() is false. + bool HandleComment(Token &Token, SourceRange Comment); +}; + +/// \brief Abstract base class that describes a handler that will receive +/// source ranges for each of the comments encountered in the source file. +class CommentHandler { +public: + virtual ~CommentHandler(); + + // The handler shall return true if it has pushed any tokens + // to be read using e.g. EnterToken or EnterTokenStream. + virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h new file mode 100644 index 0000000..477a213 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h @@ -0,0 +1,162 @@ +//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- 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 PreprocessorLexer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PreprocessorLexer_H +#define LLVM_CLANG_PreprocessorLexer_H + +#include "clang/Lex/MultipleIncludeOpt.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/SmallVector.h" +#include <string> + +namespace clang { + +class FileEntry; +class Preprocessor; + +class PreprocessorLexer { +protected: + Preprocessor *PP; // Preprocessor object controlling lexing. + + /// The SourceManager FileID corresponding to the file being lexed. + const FileID FID; + + //===--------------------------------------------------------------------===// + // Context-specific lexing flags set by the preprocessor. + //===--------------------------------------------------------------------===// + + /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns + /// '\n' into a tok::eom token. + bool ParsingPreprocessorDirective; + + /// ParsingFilename - True after #include: this turns <xx> into a + /// tok::angle_string_literal token. + bool ParsingFilename; + + /// LexingRawMode - True if in raw mode: This flag disables interpretation of + /// tokens and is a far faster mode to lex in than non-raw-mode. This flag: + /// 1. If EOF of the current lexer is found, the include stack isn't popped. + /// 2. Identifier information is not looked up for identifier tokens. As an + /// effect of this, implicit macro expansion is naturally disabled. + /// 3. "#" tokens at the start of a line are treated as normal tokens, not + /// implicitly transformed by the lexer. + /// 4. All diagnostic messages are disabled. + /// 5. No callbacks are made into the preprocessor. + /// + /// Note that in raw mode that the PP pointer may be null. + bool LexingRawMode; + + /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file + /// idiom for the multiple-include optimization. + MultipleIncludeOpt MIOpt; + + /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks + /// we are currently in. + llvm::SmallVector<PPConditionalInfo, 4> ConditionalStack; + + PreprocessorLexer(const PreprocessorLexer&); // DO NOT IMPLEMENT + void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT + friend class Preprocessor; + + PreprocessorLexer(Preprocessor *pp, FileID fid) + : PP(pp), FID(fid), ParsingPreprocessorDirective(false), + ParsingFilename(false), LexingRawMode(false) {} + + PreprocessorLexer() + : PP(0), + ParsingPreprocessorDirective(false), + ParsingFilename(false), + LexingRawMode(false) {} + + virtual ~PreprocessorLexer() {} + + virtual void IndirectLex(Token& Result) = 0; + + /// getSourceLocation - Return the source location for the next observable + /// location. + virtual SourceLocation getSourceLocation() = 0; + + //===--------------------------------------------------------------------===// + // #if directive handling. + + /// pushConditionalLevel - When we enter a #if directive, this keeps track of + /// what we are currently in for diagnostic emission (e.g. #if with missing + /// #endif). + void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, + bool FoundNonSkip, bool FoundElse) { + PPConditionalInfo CI; + CI.IfLoc = DirectiveStart; + CI.WasSkipping = WasSkipping; + CI.FoundNonSkip = FoundNonSkip; + CI.FoundElse = FoundElse; + ConditionalStack.push_back(CI); + } + void pushConditionalLevel(const PPConditionalInfo &CI) { + ConditionalStack.push_back(CI); + } + + /// popConditionalLevel - Remove an entry off the top of the conditional + /// stack, returning information about it. If the conditional stack is empty, + /// this returns true and does not fill in the arguments. + bool popConditionalLevel(PPConditionalInfo &CI) { + if (ConditionalStack.empty()) return true; + CI = ConditionalStack.back(); + ConditionalStack.pop_back(); + return false; + } + + /// peekConditionalLevel - Return the top of the conditional stack. This + /// requires that there be a conditional active. + PPConditionalInfo &peekConditionalLevel() { + assert(!ConditionalStack.empty() && "No conditionals active!"); + return ConditionalStack.back(); + } + + unsigned getConditionalStackDepth() const { return ConditionalStack.size(); } + +public: + + //===--------------------------------------------------------------------===// + // Misc. lexing methods. + + /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and + /// (potentially) macro expand the filename. If the sequence parsed is not + /// lexically legal, emit a diagnostic and return a result EOM token. + void LexIncludeFilename(Token &Result); + + /// setParsingPreprocessorDirective - Inform the lexer whether or not + /// we are currently lexing a preprocessor directive. + void setParsingPreprocessorDirective(bool f) { + ParsingPreprocessorDirective = f; + } + + /// isLexingRawMode - Return true if this lexer is in raw mode or not. + bool isLexingRawMode() const { return LexingRawMode; } + + /// getPP - Return the preprocessor object for this lexer. + Preprocessor *getPP() const { return PP; } + + FileID getFileID() const { + assert(PP && + "PreprocessorLexer::getFileID() should only be used with a Preprocessor"); + return FID; + } + + /// getFileEntry - Return the FileEntry corresponding to this FileID. Like + /// getFileID(), this only works for lexers with attached preprocessors. + const FileEntry *getFileEntry() const; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h b/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h new file mode 100644 index 0000000..f03515f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h @@ -0,0 +1,45 @@ +//===--- ScratchBuffer.h - Scratch space for forming tokens -----*- 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 ScratchBuffer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SCRATCHBUFFER_H +#define LLVM_CLANG_SCRATCHBUFFER_H + +#include "clang/Basic/SourceLocation.h" + +namespace clang { + class SourceManager; + +/// ScratchBuffer - This class exposes a simple interface for the dynamic +/// construction of tokens. This is used for builtin macros (e.g. __LINE__) as +/// well as token pasting, etc. +class ScratchBuffer { + SourceManager &SourceMgr; + char *CurBuffer; + SourceLocation BufferStartLoc; + unsigned BytesUsed; +public: + ScratchBuffer(SourceManager &SM); + + /// getToken - Splat the specified text into a temporary MemoryBuffer and + /// return a SourceLocation that refers to the token. This is just like the + /// previous method, but returns a location that indicates the physloc of the + /// token. + SourceLocation getToken(const char *Buf, unsigned Len, const char *&DestPtr); + +private: + void AllocScratchBuffer(unsigned RequestLen); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Token.h b/contrib/llvm/tools/clang/include/clang/Lex/Token.h new file mode 100644 index 0000000..b5dde9a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h @@ -0,0 +1,257 @@ +//===--- Token.h - Token interface ------------------------------*- 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 Token interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOKEN_H +#define LLVM_CLANG_TOKEN_H + +#include "clang/Basic/TemplateKinds.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/OperatorKinds.h" +#include <cstdlib> + +namespace clang { + +class IdentifierInfo; + +/// Token - This structure provides full information about a lexed token. +/// It is not intended to be space efficient, it is intended to return as much +/// information as possible about each returned token. This is expected to be +/// compressed into a smaller form if memory footprint is important. +/// +/// The parser can create a special "annotation token" representing a stream of +/// tokens that were parsed and semantically resolved, e.g.: "foo::MyClass<int>" +/// can be represented by a single typename annotation token that carries +/// information about the SourceRange of the tokens and the type object. +class Token { + /// The location of the token. + SourceLocation Loc; + + // Conceptually these next two fields could be in a union. However, this + // causes gcc 4.2 to pessimize LexTokenInternal, a very performance critical + // routine. Keeping as separate members with casts until a more beautiful fix + // presents itself. + + /// UintData - This holds either the length of the token text, when + /// a normal token, or the end of the SourceRange when an annotation + /// token. + unsigned UintData; + + /// PtrData - This is a union of four different pointer types, which depends + /// on what type of token this is: + /// Identifiers, keywords, etc: + /// This is an IdentifierInfo*, which contains the uniqued identifier + /// spelling. + /// Literals: isLiteral() returns true. + /// This is a pointer to the start of the token in a text buffer, which + /// may be dirty (have trigraphs / escaped newlines). + /// Annotations (resolved type names, C++ scopes, etc): isAnnotation(). + /// This is a pointer to sema-specific data for the annotation token. + /// Other: + /// This is null. + void *PtrData; + + /// Kind - The actual flavor of token this is. + /// + unsigned char Kind; // DON'T make Kind a 'tok::TokenKind'; + // MSVC will treat it as a signed char and + // TokenKinds > 127 won't be handled correctly. + + /// Flags - Bits we track about this token, members of the TokenFlags enum. + unsigned char Flags; +public: + + // Various flags set per token: + enum TokenFlags { + StartOfLine = 0x01, // At start of line or only after whitespace. + LeadingSpace = 0x02, // Whitespace exists before this token. + DisableExpand = 0x04, // This identifier may never be macro expanded. + NeedsCleaning = 0x08 // Contained an escaped newline or trigraph. + }; + + tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } + void setKind(tok::TokenKind K) { Kind = K; } + + /// is/isNot - Predicates to check if this token is a specific kind, as in + /// "if (Tok.is(tok::l_brace)) {...}". + bool is(tok::TokenKind K) const { return Kind == (unsigned) K; } + bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; } + + /// isLiteral - Return true if this is a "literal", like a numeric + /// constant, string, etc. + bool isLiteral() const { + return is(tok::numeric_constant) || is(tok::char_constant) || + is(tok::string_literal) || is(tok::wide_string_literal) || + is(tok::angle_string_literal); + } + + bool isAnnotation() const { + return is(tok::annot_typename) || + is(tok::annot_cxxscope) || + is(tok::annot_template_id); + } + + /// getLocation - Return a source location identifier for the specified + /// offset in the current file. + SourceLocation getLocation() const { return Loc; } + unsigned getLength() const { + assert(!isAnnotation() && "Annotation tokens have no length field"); + return UintData; + } + + void setLocation(SourceLocation L) { Loc = L; } + void setLength(unsigned Len) { + assert(!isAnnotation() && "Annotation tokens have no length field"); + UintData = Len; + } + + SourceLocation getAnnotationEndLoc() const { + assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token"); + return SourceLocation::getFromRawEncoding(UintData); + } + void setAnnotationEndLoc(SourceLocation L) { + assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token"); + UintData = L.getRawEncoding(); + } + + SourceLocation getLastLoc() const { + return isAnnotation() ? getAnnotationEndLoc() : getLocation(); + } + + /// getAnnotationRange - SourceRange of the group of tokens that this + /// annotation token represents. + SourceRange getAnnotationRange() const { + return SourceRange(getLocation(), getAnnotationEndLoc()); + } + void setAnnotationRange(SourceRange R) { + setLocation(R.getBegin()); + setAnnotationEndLoc(R.getEnd()); + } + + const char *getName() const { + return tok::getTokenName( (tok::TokenKind) Kind); + } + + /// startToken - Reset all flags to cleared. + /// + void startToken() { + Kind = tok::unknown; + Flags = 0; + PtrData = 0; + Loc = SourceLocation(); + } + + IdentifierInfo *getIdentifierInfo() const { + assert(!isAnnotation() && "Used IdentInfo on annotation token!"); + if (isLiteral()) return 0; + return (IdentifierInfo*) PtrData; + } + void setIdentifierInfo(IdentifierInfo *II) { + PtrData = (void*) II; + } + + /// getLiteralData - For a literal token (numeric constant, string, etc), this + /// returns a pointer to the start of it in the text buffer if known, null + /// otherwise. + const char *getLiteralData() const { + assert(isLiteral() && "Cannot get literal data of non-literal"); + return reinterpret_cast<const char*>(PtrData); + } + void setLiteralData(const char *Ptr) { + assert(isLiteral() && "Cannot set literal data of non-literal"); + PtrData = (void*)Ptr; + } + + void *getAnnotationValue() const { + assert(isAnnotation() && "Used AnnotVal on non-annotation token"); + return PtrData; + } + void setAnnotationValue(void *val) { + assert(isAnnotation() && "Used AnnotVal on non-annotation token"); + PtrData = val; + } + + /// setFlag - Set the specified flag. + void setFlag(TokenFlags Flag) { + Flags |= Flag; + } + + /// clearFlag - Unset the specified flag. + void clearFlag(TokenFlags Flag) { + Flags &= ~Flag; + } + + /// getFlags - Return the internal represtation of the flags. + /// Only intended for low-level operations such as writing tokens to + // disk. + unsigned getFlags() const { + return Flags; + } + + /// setFlagValue - Set a flag to either true or false. + void setFlagValue(TokenFlags Flag, bool Val) { + if (Val) + setFlag(Flag); + else + clearFlag(Flag); + } + + /// isAtStartOfLine - Return true if this token is at the start of a line. + /// + bool isAtStartOfLine() const { return (Flags & StartOfLine) ? true : false; } + + /// hasLeadingSpace - Return true if this token has whitespace before it. + /// + bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; } + + /// isExpandDisabled - Return true if this identifier token should never + /// be expanded in the future, due to C99 6.10.3.4p2. + bool isExpandDisabled() const { + return (Flags & DisableExpand) ? true : false; + } + + /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier. + bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const; + + /// getObjCKeywordID - Return the ObjC keyword kind. + tok::ObjCKeywordKind getObjCKeywordID() const; + + /// needsCleaning - Return true if this token has trigraphs or escaped + /// newlines in it. + /// + bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; } +}; + +/// PPConditionalInfo - Information about the conditional stack (#if directives) +/// currently active. +struct PPConditionalInfo { + /// IfLoc - Location where the conditional started. + /// + SourceLocation IfLoc; + + /// WasSkipping - True if this was contained in a skipping directive, e.g. + /// in a "#if 0" block. + bool WasSkipping; + + /// FoundNonSkip - True if we have emitted tokens already, and now we're in + /// an #else block or something. Only useful in Skipping blocks. + bool FoundNonSkip; + + /// FoundElse - True if we've seen a #else in this block. If so, + /// #elif/#else directives are not allowed. + bool FoundElse; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h new file mode 100644 index 0000000..094990a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h @@ -0,0 +1,75 @@ +//===--- TokenConcatenation.h - Token Concatenation Avoidance ---*- 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 TokenConcatenation class. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_LEX_TOKEN_CONCATENATION_H +#define CLANG_LEX_TOKEN_CONCATENATION_H + +#include "clang/Basic/TokenKinds.h" + +namespace clang { + class Preprocessor; + class Token; + + /// TokenConcatenation class, which answers the question of + /// "Is it safe to emit two tokens without a whitespace between them, or + /// would that cause implicit concatenation of the tokens?" + /// + /// For example, it emitting two identifiers "foo" and "bar" next to each + /// other would cause the lexer to produce one "foobar" token. Emitting "1" + /// and ")" next to each other is safe. + /// + class TokenConcatenation { + Preprocessor &PP; + + enum AvoidConcatInfo { + /// By default, a token never needs to avoid concatenation. Most tokens + /// (e.g. ',', ')', etc) don't cause a problem when concatenated. + aci_never_avoid_concat = 0, + + /// aci_custom_firstchar - AvoidConcat contains custom code to handle this + /// token's requirements, and it needs to know the first character of the + /// token. + aci_custom_firstchar = 1, + + /// aci_custom - AvoidConcat contains custom code to handle this token's + /// requirements, but it doesn't need to know the first character of the + /// token. + aci_custom = 2, + + /// aci_avoid_equal - Many tokens cannot be safely followed by an '=' + /// character. For example, "<<" turns into "<<=" when followed by an =. + aci_avoid_equal = 4 + }; + + /// TokenInfo - This array contains information for each token on what + /// action to take when avoiding concatenation of tokens in the AvoidConcat + /// method. + char TokenInfo[tok::NUM_TOKENS]; + public: + TokenConcatenation(Preprocessor &PP); + + bool AvoidConcat(const Token &PrevPrevTok, + const Token &PrevTok, + const Token &Tok) const; + + private: + /// StartsWithL - Return true if the spelling of this token starts with 'L'. + bool StartsWithL(const Token &Tok) const; + + /// IsIdentifierL - Return true if the spelling of this token is literally + /// 'L'. + bool IsIdentifierL(const Token &Tok) const; + }; + } // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h new file mode 100644 index 0000000..3f13e9c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h @@ -0,0 +1,154 @@ +//===--- TokenLexer.h - Lex from a token buffer -----------------*- 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 TokenLexer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOKENLEXER_H +#define LLVM_CLANG_TOKENLEXER_H + +#include "clang/Basic/SourceLocation.h" + +namespace clang { + class MacroInfo; + class Preprocessor; + class Token; + class MacroArgs; + +/// TokenLexer - This implements a lexer that returns token from a macro body +/// or token stream instead of lexing from a character buffer. This is used for +/// macro expansion and _Pragma handling, for example. +/// +class TokenLexer { + /// Macro - The macro we are expanding from. This is null if expanding a + /// token stream. + /// + MacroInfo *Macro; + + /// ActualArgs - The actual arguments specified for a function-like macro, or + /// null. The TokenLexer owns the pointed-to object. + MacroArgs *ActualArgs; + + /// PP - The current preprocessor object we are expanding for. + /// + Preprocessor &PP; + + /// Tokens - This is the pointer to an array of tokens that the macro is + /// defined to, with arguments expanded for function-like macros. If this is + /// a token stream, these are the tokens we are returning. This points into + /// the macro definition we are lexing from, a scratch buffer allocated from + /// the preprocessor's bump pointer allocator, or some other buffer that we + /// may or may not own (depending on OwnsTokens). + const Token *Tokens; + + /// NumTokens - This is the length of the Tokens array. + /// + unsigned NumTokens; + + /// CurToken - This is the next token that Lex will return. + /// + unsigned CurToken; + + /// InstantiateLocStart/End - The source location range where this macro was + /// instantiated. + SourceLocation InstantiateLocStart, InstantiateLocEnd; + + /// Lexical information about the expansion point of the macro: the identifier + /// that the macro expanded from had these properties. + bool AtStartOfLine : 1; + bool HasLeadingSpace : 1; + + /// OwnsTokens - This is true if this TokenLexer allocated the Tokens + /// array, and thus needs to free it when destroyed. For simple object-like + /// macros (for example) we just point into the token buffer of the macro + /// definition, we don't make a copy of it. + bool OwnsTokens : 1; + + /// DisableMacroExpansion - This is true when tokens lexed from the TokenLexer + /// should not be subject to further macro expansion. + bool DisableMacroExpansion : 1; + + TokenLexer(const TokenLexer&); // DO NOT IMPLEMENT + void operator=(const TokenLexer&); // DO NOT IMPLEMENT +public: + /// Create a TokenLexer for the specified macro with the specified actual + /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. + /// ILEnd specifies the location of the ')' for a function-like macro or the + /// identifier for an object-like macro. + TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs, + Preprocessor &pp) + : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { + Init(Tok, ILEnd, ActualArgs); + } + + /// Init - Initialize this TokenLexer to expand from the specified macro + /// with the specified argument information. Note that this ctor takes + /// ownership of the ActualArgs pointer. ILEnd specifies the location of the + /// ')' for a function-like macro or the identifier for an object-like macro. + void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs); + + /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is + /// specified, this takes ownership of the tokens and delete[]'s them when + /// the token lexer is empty. + TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion, + bool ownsTokens, Preprocessor &pp) + : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { + Init(TokArray, NumToks, DisableExpansion, ownsTokens); + } + + /// Init - Initialize this TokenLexer with the specified token stream. + /// This does not take ownership of the specified token vector. + /// + /// DisableExpansion is true when macro expansion of tokens lexed from this + /// stream should be disabled. + void Init(const Token *TokArray, unsigned NumToks, + bool DisableMacroExpansion, bool OwnsTokens); + + ~TokenLexer() { destroy(); } + + /// isNextTokenLParen - If the next token lexed will pop this macro off the + /// expansion stack, return 2. If the next unexpanded token is a '(', return + /// 1, otherwise return 0. + unsigned isNextTokenLParen() const; + + /// Lex - Lex and return a token from this macro stream. + void Lex(Token &Tok); + +private: + void destroy(); + + /// isAtEnd - Return true if the next lex call will pop this macro off the + /// include stack. + bool isAtEnd() const { + return CurToken == NumTokens; + } + + /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ## + /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there + /// are is another ## after it, chomp it iteratively. Return the result as + /// Tok. If this returns true, the caller should immediately return the + /// token. + bool PasteTokens(Token &Tok); + + /// Expand the arguments of a function-like macro so that we can quickly + /// return preexpanded tokens from Tokens. + void ExpandFunctionArguments(); + + /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes + /// together to form a comment that comments out everything in the current + /// macro, other active macros, and anything left on the current physical + /// source line of the instantiated buffer. Handle this by returning the + /// first token on the next line. + void HandleMicrosoftCommentPaste(Token &Tok); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Makefile b/contrib/llvm/tools/clang/include/clang/Makefile new file mode 100644 index 0000000..6abe375 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Makefile @@ -0,0 +1,31 @@ +LEVEL = ../../../.. +DIRS := AST Basic Driver + +include $(LEVEL)/Makefile.common + +install-local:: + $(Echo) Installing Clang include files + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include/clang" ; then \ + cd $(PROJ_SRC_ROOT)/tools/clang/include && \ + for hdr in `find clang -type f '!' '(' -name '*~' \ + -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ + -o -name 'Makefile' -o -name '*.td' -o -name '*.orig' ')' -print \ + | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ + instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang" ; then \ + cd $(PROJ_OBJ_ROOT)/tools/clang/include && \ + for hdr in `find clang -type f '!' '(' -name 'Makefile' ')' -print \ + | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Action.h b/contrib/llvm/tools/clang/include/clang/Parse/Action.h new file mode 100644 index 0000000..e21da81 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Action.h @@ -0,0 +1,3122 @@ +//===--- Action.h - Parser Action Interface ---------------------*- 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 Action and EmptyAction interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_ACTION_H +#define LLVM_CLANG_PARSE_ACTION_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TemplateKinds.h" +#include "clang/Basic/TypeTraits.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Ownership.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + // Semantic. + class DeclSpec; + class ObjCDeclSpec; + class CXXScopeSpec; + class Declarator; + class AttributeList; + struct FieldDeclarator; + // Parse. + class Scope; + class Action; + class Selector; + class Designation; + class InitListDesignations; + // Lex. + class Preprocessor; + class Token; + + // We can re-use the low bit of expression, statement, base, and + // member-initializer pointers for the "invalid" flag of + // ActionResult. + template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;}; + +/// Action - As the parser reads the input file and recognizes the productions +/// of the grammar, it invokes methods on this class to turn the parsed input +/// into something useful: e.g. a parse tree. +/// +/// The callback methods that this class provides are phrased as actions that +/// the parser has just done or is about to do when the method is called. They +/// are not requests that the actions module do the specified action. +/// +/// All of the methods here are optional except getTypeName() and +/// isCurrentClassName(), which must be specified in order for the +/// parse to complete accurately. The MinimalAction class does this +/// bare-minimum of tracking to implement this functionality. +class Action : public ActionBase { +public: + /// Out-of-line virtual destructor to provide home for this class. + virtual ~Action(); + + // Types - Though these don't actually enforce strong typing, they document + // what types are required to be identical for the actions. + typedef ActionBase::ExprTy ExprTy; + typedef ActionBase::StmtTy StmtTy; + + /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap + /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and + /// allowing for failure. + typedef ActionResult<0> ExprResult; + typedef ActionResult<1> StmtResult; + typedef ActionResult<2> TypeResult; + typedef ActionResult<3> BaseResult; + typedef ActionResult<4> MemInitResult; + typedef ActionResult<5, DeclPtrTy> DeclResult; + + /// Same, but with ownership. + typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult; + typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult; + // Note that these will replace ExprResult and StmtResult when the transition + // is complete. + + /// Single expressions or statements as arguments. +#if !defined(DISABLE_SMART_POINTERS) + typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg; + typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg; +#else + typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg; + typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg; +#endif + + /// Multiple expressions or statements as arguments. + typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg; + typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg; + typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg; + + class FullExprArg { + public: + FullExprArg(ActionBase &actions) : Expr(actions) { } + + // 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). + FullExprArg(const FullExprArg& Other) + : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {} + + FullExprArg &operator=(const FullExprArg& Other) { + Expr.operator=(move(const_cast<FullExprArg&>(Other).Expr)); + return *this; + } + + OwningExprResult release() { + return move(Expr); + } + + ExprArg* operator->() { + return &Expr; + } + + private: + // FIXME: No need to make the entire Action class a friend when it's just + // Action::FullExpr that needs access to the constructor below. + friend class Action; + + explicit FullExprArg(ExprArg expr) + : Expr(move(expr)) {} + + ExprArg Expr; + }; + + template<typename T> + FullExprArg MakeFullExpr(T &Arg) { + return FullExprArg(ActOnFinishFullExpr(move(Arg))); + } + + // Utilities for Action implementations to return smart results. + + OwningExprResult ExprError() { return OwningExprResult(*this, true); } + OwningStmtResult StmtError() { return OwningStmtResult(*this, true); } + + OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } + OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } + + OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); } + OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); } + + /// Statistics. + virtual void PrintStats() const {} + + /// getDeclName - Return a pretty name for the specified decl if possible, or + /// an empty string if not. This is used for pretty crash reporting. + virtual std::string getDeclName(DeclPtrTy D) { return ""; } + + //===--------------------------------------------------------------------===// + // Declaration Tracking Callbacks. + //===--------------------------------------------------------------------===// + + typedef uintptr_t ParsingDeclStackState; + + /// PushParsingDeclaration - Notes that the parser has begun + /// processing a declaration of some sort. Guaranteed to be matched + /// by a call to PopParsingDeclaration with the value returned by + /// this method. + virtual ParsingDeclStackState PushParsingDeclaration() { + return ParsingDeclStackState(); + } + + /// PopParsingDeclaration - Notes that the parser has completed + /// processing a declaration of some sort. The decl will be empty + /// if the declaration didn't correspond to a full declaration (or + /// if the actions module returned an empty decl for it). + virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) { + } + + /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it + /// needs a decl group, it calls this to convert between the two + /// representations. + virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) { + return DeclGroupPtrTy(); + } + + /// getTypeName - Return non-null if the specified identifier is a type name + /// in the current scope. + /// + /// \param II the identifier for which we are performing name lookup + /// + /// \param NameLoc the location of the identifier + /// + /// \param S the scope in which this name lookup occurs + /// + /// \param SS if non-NULL, the C++ scope specifier that precedes the + /// identifier + /// + /// \param isClassName whether this is a C++ class-name production, in + /// which we can end up referring to a member of an unknown specialization + /// that we know (from the grammar) is supposed to be a type. For example, + /// this occurs when deriving from "std::vector<T>::allocator_type", where T + /// is a template parameter. + /// + /// \param ObjectType if we're checking whether an identifier is a type + /// within a C++ member access expression, this will be the type of the + /// + /// \returns the type referred to by this identifier, or NULL if the type + /// does not name an identifier. + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS = 0, + bool isClassName = false, + TypeTy *ObjectType = 0) = 0; + + /// isTagName() - This method is called *for error recovery purposes only* + /// to determine if the specified name is a valid tag name ("struct foo"). If + /// so, this returns the TST for the tag corresponding to it (TST_enum, + /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C + /// where the user forgot to specify the tag. + virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) { + return DeclSpec::TST_unspecified; + } + + /// \brief Action called as part of error recovery when the parser has + /// determined that the given name must refer to a type, but + /// \c getTypeName() did not return a result. + /// + /// This callback permits the action to give a detailed diagnostic when an + /// unknown type name is encountered and, potentially, to try to recover + /// by producing a new type in \p SuggestedType. + /// + /// \param II the name that should be a type. + /// + /// \param IILoc the location of the name in the source. + /// + /// \param S the scope in which name lookup was performed. + /// + /// \param SS if non-NULL, the C++ scope specifier that preceded the name. + /// + /// \param SuggestedType if the action sets this type to a non-NULL type, + /// the parser will recovery by consuming the type name token and then + /// pretending that the given type was the type it parsed. + /// + /// \returns true if a diagnostic was emitted, false otherwise. When false, + /// the parser itself will emit a generic "unknown type name" diagnostic. + virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + CXXScopeSpec *SS, + TypeTy *&SuggestedType) { + return false; + } + + /// isCurrentClassName - Return true if the specified name is the + /// name of the innermost C++ class type currently being defined. + virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, + const CXXScopeSpec *SS = 0) = 0; + + /// \brief Determine whether the given name refers to a template. + /// + /// This callback is used by the parser after it has seen a '<' to determine + /// whether the given name refers to a template and, if so, what kind of + /// template. + /// + /// \param S the scope in which the name occurs. + /// + /// \param SS the C++ nested-name-specifier that precedes the template name, + /// if any. + /// + /// \param Name the name that we are querying to determine whether it is + /// a template. + /// + /// \param ObjectType if we are determining whether the given name is a + /// template name in the context of a member access expression (e.g., + /// \c p->X<int>), this is the type of the object referred to by the + /// member access (e.g., \c p). + /// + /// \param EnteringContext whether we are potentially entering the context + /// referred to by the nested-name-specifier \p SS, which allows semantic + /// analysis to look into uninstantiated templates. + /// + /// \param Template if the name does refer to a template, the declaration + /// of the template that the name refers to. + /// + /// \param MemberOfUnknownSpecialization Will be set true if the resulting + /// member would be a member of an unknown specialization, in which case this + /// lookup cannot possibly pass at this time. + /// + /// \returns the kind of template that this name refers to. + virtual TemplateNameKind isTemplateName(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization) = 0; + + /// \brief Action called as part of error recovery when the parser has + /// determined that the given name must refer to a template, but + /// \c isTemplateName() did not return a result. + /// + /// This callback permits the action to give a detailed diagnostic when an + /// unknown template name is encountered and, potentially, to try to recover + /// by producing a new template in \p SuggestedTemplate. + /// + /// \param II the name that should be a template. + /// + /// \param IILoc the location of the name in the source. + /// + /// \param S the scope in which name lookup was performed. + /// + /// \param SS the C++ scope specifier that preceded the name. + /// + /// \param SuggestedTemplate if the action sets this template to a non-NULL, + /// template, the parser will recover by consuming the template name token + /// and the template argument list that follows. + /// + /// \param SuggestedTemplateKind as input, the kind of template that we + /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the + /// action provides a suggested template, this should be set to the kind of + /// template. + /// + /// \returns true if a diagnostic was emitted, false otherwise. When false, + /// the parser itself will emit a generic "unknown template name" diagnostic. + virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind) { + return false; + } + + /// \brief Determine whether the given name refers to a non-type nested name + /// specifier, e.g., the name of a namespace or namespace alias. + /// + /// This actual is used in the parsing of pseudo-destructor names to + /// distinguish a nested-name-specifier and a "type-name ::" when we + /// see the token sequence "X :: ~". + virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, + SourceLocation IdLoc, + IdentifierInfo &II, + TypeTy *ObjectType) { + return false; + } + + /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the + /// global scope ('::'). + virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S, + SourceLocation CCLoc) { + return 0; + } + + /// \brief Parsed an identifier followed by '::' in a C++ + /// nested-name-specifier. + /// + /// \param S the scope in which the nested-name-specifier was parsed. + /// + /// \param SS the nested-name-specifier that precedes the identifier. For + /// example, if we are parsing "foo::bar::", \p SS will describe the "foo::" + /// that has already been parsed. + /// + /// \param IdLoc the location of the identifier we have just parsed (e.g., + /// the "bar" in "foo::bar::". + /// + /// \param CCLoc the location of the '::' at the end of the + /// nested-name-specifier. + /// + /// \param II the identifier that represents the scope that this + /// nested-name-specifier refers to, e.g., the "bar" in "foo::bar::". + /// + /// \param ObjectType if this nested-name-specifier occurs as part of a + /// C++ member access expression such as "x->Base::f", the type of the base + /// object (e.g., *x in the example, if "x" were a pointer). + /// + /// \param EnteringContext if true, then we intend to immediately enter the + /// context of this nested-name-specifier, e.g., for an out-of-line + /// definition of a class member. + /// + /// \returns a CXXScopeTy* object representing the C++ scope. + virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, + CXXScopeSpec &SS, + SourceLocation IdLoc, + SourceLocation CCLoc, + IdentifierInfo &II, + TypeTy *ObjectType, + bool EnteringContext) { + return 0; + } + + /// IsInvalidUnlessNestedName - This method is used for error recovery + /// purposes to determine whether the specified identifier is only valid as + /// a nested name specifier, for example a namespace name. It is + /// conservatively correct to always return false from this method. + /// + /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. + virtual bool IsInvalidUnlessNestedName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo &II, + TypeTy *ObjectType, + bool EnteringContext) { + return false; + } + + /// ActOnCXXNestedNameSpecifier - Called during parsing of a + /// nested-name-specifier that involves a template-id, e.g., + /// "foo::bar<int, float>::", and now we need to build a scope + /// specifier. \p SS is empty or the previously parsed nested-name + /// part ("foo::"), \p Type is the already-parsed class template + /// specialization (or other template-id that names a type), \p + /// TypeRange is the source range where the type is located, and \p + /// CCLoc is the location of the trailing '::'. + virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, + const CXXScopeSpec &SS, + TypeTy *Type, + SourceRange TypeRange, + SourceLocation CCLoc) { + return 0; + } + + /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier + /// is parsed as part of a declarator-id to determine whether a scope + /// should be entered. + /// + /// \param S the current scope + /// \param SS the scope being entered + /// \param isFriendDeclaration whether this is a friend declaration + virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + return false; + } + + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global + /// scope or nested-name-specifier) is parsed as part of a declarator-id. + /// After this method is called, according to [C++ 3.4.3p3], names should be + /// looked up in the declarator-id's scope, until the declarator is parsed and + /// ActOnCXXExitDeclaratorScope is called. + /// The 'SS' should be a non-empty valid CXXScopeSpec. + /// \returns true if an error occurred, false otherwise. + virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { + return false; + } + + /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously + /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same + /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. + /// Used to indicate that names should revert to being looked up in the + /// defining scope. + virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + } + + /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an + /// initializer for the declaration 'Dcl'. + /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a + /// static data member of class X, names should be looked up in the scope of + /// class X. + virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { + } + + /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an + /// initializer for the declaration 'Dcl'. + virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { + } + + /// ActOnDeclarator - This callback is invoked when a declarator is parsed and + /// 'Init' specifies the initializer if any. This is for things like: + /// "int X = 4" or "typedef int foo". + /// + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + /// ActOnParamDeclarator - This callback is invoked when a parameter + /// declarator is parsed. This callback only occurs for functions + /// with prototypes. S is the function prototype scope for the + /// parameters (C++ [basic.scope.proto]). + virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + /// \brief Parsed an exception object declaration within an Objective-C + /// @catch statement. + virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + /// AddInitializerToDecl - This action is called immediately after + /// ActOnDeclarator (when an initializer is present). The code is factored + /// this way to make sure we are able to handle the following: + /// void func() { int xx = xx; } + /// This allows ActOnDeclarator to register "xx" prior to parsing the + /// initializer. The declaration above should still result in a warning, + /// since the reference to "xx" is uninitialized. + virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) { + return; + } + + /// SetDeclDeleted - This action is called immediately after ActOnDeclarator + /// if =delete is parsed. C++0x [dcl.fct.def]p10 + /// Note that this can be called even for variable declarations. It's the + /// action's job to reject it. + virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) { + return; + } + + /// ActOnUninitializedDecl - This action is called immediately after + /// ActOnDeclarator (when an initializer is *not* present). + /// If TypeContainsUndeducedAuto is true, then the type of the declarator + /// has an undeduced 'auto' type somewhere. + virtual void ActOnUninitializedDecl(DeclPtrTy Dcl, + bool TypeContainsUndeducedAuto) { + return; + } + + /// \brief Note that the given declaration had an initializer that could not + /// be parsed. + virtual void ActOnInitializerError(DeclPtrTy Dcl) { + return; + } + + /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this + /// gives the actions implementation a chance to process the group as a whole. + virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, + DeclPtrTy *Group, + unsigned NumDecls) { + return DeclGroupPtrTy(); + } + + + /// @brief Indicates that all K&R-style parameter declarations have + /// been parsed prior to a function definition. + /// @param S The function prototype scope. + /// @param D The function declarator. + virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, + SourceLocation LocAfterDecls) { + } + + /// ActOnStartOfFunctionDef - This is called at the start of a function + /// definition, instead of calling ActOnDeclarator. The Declarator includes + /// information about formal arguments that are part of this function. + virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { + // Default to ActOnDeclarator. + return ActOnStartOfFunctionDef(FnBodyScope, + ActOnDeclarator(FnBodyScope, D)); + } + + /// ActOnStartOfFunctionDef - This is called at the start of a function + /// definition, after the FunctionDecl has already been created. + virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { + return D; + } + + virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { + return; + } + + /// ActOnFinishFunctionBody - This is called when a function body has + /// completed parsing. Decl is returned by ParseStartOfFunctionDef. + virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) { + return Decl; + } + + virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, + ExprArg AsmString) { + return DeclPtrTy(); + } + + /// ActOnPopScope - This callback is called immediately before the specified + /// scope is popped and deleted. + virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {} + + /// ActOnTranslationUnitScope - This callback is called once, immediately + /// after creating the translation unit scope (in Parser::Initialize). + virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {} + + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with + /// no declarator (e.g. "struct foo;") is parsed. + virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, + AccessSpecifier Access, + DeclSpec &DS) { + return DeclPtrTy(); + } + + /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ + /// linkage specification, including the language and (if present) + /// the '{'. ExternLoc is the location of the 'extern', LangLoc is + /// the location of the language string literal, which is provided + /// by Lang/StrSize. LBraceLoc, if valid, provides the location of + /// the '{' brace. Otherwise, this linkage specification does not + /// have any braces. + virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S, + SourceLocation ExternLoc, + SourceLocation LangLoc, + llvm::StringRef Lang, + SourceLocation LBraceLoc) { + return DeclPtrTy(); + } + + /// ActOnFinishLinkageSpecification - Completely the definition of + /// the C++ linkage specification LinkageSpec. If RBraceLoc is + /// valid, it's the position of the closing '}' brace in a linkage + /// specification that uses braces. + virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S, + DeclPtrTy LinkageSpec, + SourceLocation RBraceLoc) { + return LinkageSpec; + } + + /// ActOnEndOfTranslationUnit - This is called at the very end of the + /// translation unit when EOF is reached and all but the top-level scope is + /// popped. + virtual void ActOnEndOfTranslationUnit() {} + + //===--------------------------------------------------------------------===// + // Type Parsing Callbacks. + //===--------------------------------------------------------------------===// + + /// ActOnTypeName - A type-name (type-id in C++) was parsed. + virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) { + return TypeResult(); + } + + enum TagUseKind { + TUK_Reference, // Reference to a tag: 'struct foo *X;' + TUK_Declaration, // Fwd decl of a tag: 'struct foo;' + TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;' + TUK_Friend // Friend declaration: 'friend struct foo;' + }; + + /// \brief The parser has encountered a tag (e.g., "class X") that should be + /// turned into a declaration by the action module. + /// + /// \param S the scope in which this tag occurs. + /// + /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag + /// this is (struct/union/enum/class). + /// + /// \param TUK how the tag we have encountered is being used, which + /// can be a reference to a (possibly pre-existing) tag, a + /// declaration of that tag, or the beginning of a definition of + /// that tag. + /// + /// \param KWLoc the location of the "struct", "class", "union", or "enum" + /// keyword. + /// + /// \param SS C++ scope specifier that precedes the name of the tag, e.g., + /// the "std::" in "class std::type_info". + /// + /// \param Name the name of the tag, e.g., "X" in "struct X". This parameter + /// may be NULL, to indicate an anonymous class/struct/union/enum type. + /// + /// \param NameLoc the location of the name of the tag. + /// + /// \param Attr the set of attributes that appertain to the tag. + /// + /// \param AS when this tag occurs within a C++ class, provides the + /// current access specifier (AS_public, AS_private, AS_protected). + /// Otherwise, it will be AS_none. + /// + /// \param TemplateParameterLists the set of C++ template parameter lists + /// that apply to this tag, if the tag is a declaration or definition (see + /// the \p TK parameter). The action module is responsible for determining, + /// based on the template parameter lists and the scope specifier, whether + /// the declared tag is a class template or not. + /// + /// \param OwnedDecl the callee should set this flag true when the returned + /// declaration is "owned" by this reference. Ownership is handled entirely + /// by the action module. + /// + /// \returns the declaration to which this tag refers. + virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, AccessSpecifier AS, + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent) { + return DeclPtrTy(); + } + + /// Acts on a reference to a dependent tag name. This arises in + /// cases like: + /// + /// template <class T> class A; + /// template <class T> class B { + /// friend class A<T>::M; // here + /// }; + /// + /// \param TagSpec an instance of DeclSpec::TST corresponding to the + /// tag specifier. + /// + /// \param TUK the tag use kind (either TUK_Friend or TUK_Reference) + /// + /// \param SS the scope specifier (always defined) + virtual TypeResult ActOnDependentTag(Scope *S, + unsigned TagSpec, + TagUseKind TUK, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation KWLoc, + SourceLocation NameLoc) { + return TypeResult(); + } + + /// Act on @defs() element found when parsing a structure. ClassName is the + /// name of the referenced class. + virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, + llvm::SmallVectorImpl<DeclPtrTy> &Decls) {} + virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, + SourceLocation DeclStart, + Declarator &D, ExprTy *BitfieldWidth) { + return DeclPtrTy(); + } + + virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, + DeclPtrTy IntfDecl, + Declarator &D, ExprTy *BitfieldWidth, + tok::ObjCKeywordKind visibility) { + return DeclPtrTy(); + } + + virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl, + DeclPtrTy *Fields, unsigned NumFields, + SourceLocation LBrac, SourceLocation RBrac, + AttributeList *AttrList) {} + + /// ActOnTagStartDefinition - Invoked when we have entered the + /// scope of a tag's definition (e.g., for an enumeration, class, + /// struct, or union). + virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { } + + /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a + /// C++ record definition's base-specifiers clause and are starting its + /// member declarations. + virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl, + SourceLocation LBraceLoc) { } + + /// ActOnTagFinishDefinition - Invoked once we have finished parsing + /// the definition of a tag (enumeration, class, struct, or union). + /// + /// The scope is the scope of the tag definition. + virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl, + SourceLocation RBraceLoc) { } + + /// ActOnTagDefinitionError - Invoked if there's an unrecoverable + /// error parsing the definition of a tag. + /// + /// The scope is the scope of the tag definition. + virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl) { } + + virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, + DeclPtrTy LastEnumConstant, + SourceLocation IdLoc, IdentifierInfo *Id, + SourceLocation EqualLoc, ExprTy *Val) { + return DeclPtrTy(); + } + virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, DeclPtrTy EnumDecl, + DeclPtrTy *Elements, unsigned NumElements, + Scope *S, AttributeList *AttrList) {} + + //===--------------------------------------------------------------------===// + // Statement Parsing Callbacks. + //===--------------------------------------------------------------------===// + + virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, + MultiStmtArg Elts, + bool isStmtExpr) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return StmtEmpty(); + } + + virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) { + } + + virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { + return OwningStmtResult(*this, Expr->release()); + } + + /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, + /// which can specify an RHS value. The sub-statement of the case is + /// specified in a separate action. + virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, + SourceLocation DotDotDotLoc, + ExprArg RHSVal, + SourceLocation ColonLoc) { + return StmtEmpty(); + } + + /// ActOnCaseStmtBody - This installs a statement as the body of a case. + virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {} + + virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, + StmtArg SubStmt, Scope *CurScope){ + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation ColonLoc, + StmtArg SubStmt) { + return StmtEmpty(); + } + + /// \brief Parsed an "if" statement. + /// + /// \param IfLoc the location of the "if" keyword. + /// + /// \param CondVal if the "if" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "if" condition was parsed as a condition variable, + /// the condition variable itself. + /// + /// \param ThenVal the "then" statement. + /// + /// \param ElseLoc the location of the "else" keyword. + /// + /// \param ElseVal the "else" statement. + virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, + FullExprArg CondVal, + DeclPtrTy CondVar, + StmtArg ThenVal, + SourceLocation ElseLoc, + StmtArg ElseVal) { + return StmtEmpty(); + } + + /// \brief Parsed the start of a "switch" statement. + /// + /// \param SwitchLoc The location of the "switch" keyword. + /// + /// \param Cond if the "switch" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "switch" condition was parsed as a condition + /// variable, the condition variable itself. + virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, + ExprArg Cond, + DeclPtrTy CondVar) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, + StmtArg Switch, StmtArg Body) { + return StmtEmpty(); + } + + /// \brief Parsed a "while" statement. + /// + /// \param Cond if the "while" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "while" condition was parsed as a condition + /// variable, the condition variable itself. + /// + /// \param Body the body of the "while" loop. + virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, + FullExprArg Cond, DeclPtrTy CondVar, + StmtArg Body) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, + SourceLocation WhileLoc, + SourceLocation CondLParen, + ExprArg Cond, + SourceLocation CondRParen) { + return StmtEmpty(); + } + + /// \brief Parsed a "for" statement. + /// + /// \param ForLoc the location of the "for" keyword. + /// + /// \param LParenLoc the location of the left parentheses. + /// + /// \param First the statement used to initialize the for loop. + /// + /// \param Second the condition to be checked during each iteration, if + /// that condition was parsed as an expression. + /// + /// \param SecondArg the condition variable to be checked during each + /// iterator, if that condition was parsed as a variable declaration. + /// + /// \param Third the expression that will be evaluated to "increment" any + /// values prior to the next iteration. + /// + /// \param RParenLoc the location of the right parentheses. + /// + /// \param Body the body of the "body" loop. + virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, FullExprArg Third, + SourceLocation RParenLoc, + StmtArg Body) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, + SourceLocation LParenLoc, + StmtArg First, ExprArg Second, + SourceLocation RParenLoc, StmtArg Body) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + IdentifierInfo *LabelII) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, + ExprArg DestExp) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc, + Scope *CurScope) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc, + Scope *CurScope) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, + ExprArg RetValExp) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc, + bool IsSimple, + bool IsVolatile, + unsigned NumOutputs, + unsigned NumInputs, + IdentifierInfo **Names, + MultiExprArg Constraints, + MultiExprArg Exprs, + ExprArg AsmString, + MultiExprArg Clobbers, + SourceLocation RParenLoc, + bool MSAsm = false) { + return StmtEmpty(); + } + + // Objective-c statements + + /// \brief Parsed an Objective-C @catch statement. + /// + /// \param AtLoc The location of the '@' starting the '@catch'. + /// + /// \param RParen The location of the right parentheses ')' after the + /// exception variable. + /// + /// \param Parm The variable that will catch the exception. Will be NULL if + /// this is a @catch(...) block. + /// + /// \param Body The body of the @catch block. + virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, + SourceLocation RParen, + DeclPtrTy Parm, StmtArg Body) { + return StmtEmpty(); + } + + /// \brief Parsed an Objective-C @finally statement. + /// + /// \param AtLoc The location of the '@' starting the '@finally'. + /// + /// \param Body The body of the @finally block. + virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, + StmtArg Body) { + return StmtEmpty(); + } + + /// \brief Parsed an Objective-C @try-@catch-@finally statement. + /// + /// \param AtLoc The location of the '@' starting '@try'. + /// + /// \param Try The body of the '@try' statement. + /// + /// \param CatchStmts The @catch statements. + /// + /// \param Finally The @finally statement. + virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, + StmtArg Try, + MultiStmtArg CatchStmts, + StmtArg Finally) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, + ExprArg Throw, + Scope *CurScope) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, + ExprArg SynchExpr, + StmtArg SynchBody) { + return StmtEmpty(); + } + + // C++ Statements + virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, + DeclPtrTy ExceptionDecl, + StmtArg HandlerBlock) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc, + StmtArg TryBlock, + MultiStmtArg Handlers) { + return StmtEmpty(); + } + + //===--------------------------------------------------------------------===// + // Expression Parsing Callbacks. + //===--------------------------------------------------------------------===// + + /// \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, + + /// \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 parser is entering a new expression evaluation context. + /// + /// \param NewContext is the new expression evaluation context. + virtual void + PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { } + + /// \brief The parser is exiting an expression evaluation context. + virtual void + PopExpressionEvaluationContext() { } + + // Primary Expressions. + + /// \brief Retrieve the source range that corresponds to the given + /// expression. + virtual SourceRange getExprRange(ExprTy *E) const { + return SourceRange(); + } + + /// \brief Parsed an id-expression (C++) or identifier (C) in expression + /// context, e.g., the expression "x" that refers to a variable named "x". + /// + /// \param S the scope in which this id-expression or identifier occurs. + /// + /// \param SS the C++ nested-name-specifier that qualifies the name of the + /// value, e.g., "std::" in "std::sort". + /// + /// \param Name the name to which the id-expression refers. In C, this will + /// always be an identifier. In C++, it may also be an overloaded operator, + /// destructor name (if there is a nested-name-specifier), or template-id. + /// + /// \param HasTrailingLParen whether the next token following the + /// id-expression or identifier is a left parentheses ('('). + /// + /// \param IsAddressOfOperand whether the token that precedes this + /// id-expression or identifier was an ampersand ('&'), indicating that + /// we will be taking the address of this expression. + virtual OwningExprResult ActOnIdExpression(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Name, + bool HasTrailingLParen, + bool IsAddressOfOperand) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, + tok::TokenKind Kind) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnCharacterConstant(const Token &) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnNumericConstant(const Token &) { + return ExprEmpty(); + } + + /// ActOnStringLiteral - The specified tokens were lexed as pasted string + /// fragments (e.g. "foo" "bar" L"baz"). + virtual OwningExprResult ActOnStringLiteral(const Token *Toks, + unsigned NumToks) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, + ExprArg Val) { + return move(Val); // Default impl returns operand. + } + + virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val, + TypeTy *TypeOfCast=0) { + return ExprEmpty(); + } + + // Postfix Expressions. + virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, + ExprArg Input) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base, + SourceLocation LLoc, + ExprArg Idx, + SourceLocation RLoc) { + return ExprEmpty(); + } + + /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref]) + /// of the form \c x.m or \c p->m. + /// + /// \param S the scope in which the member access expression occurs. + /// + /// \param Base the class or pointer to class into which this member + /// access expression refers, e.g., \c x in \c x.m. + /// + /// \param OpLoc the location of the "." or "->" operator. + /// + /// \param OpKind the kind of member access operator, which will be either + /// tok::arrow ("->") or tok::period ("."). + /// + /// \param SS in C++, the nested-name-specifier that precedes the member + /// name, if any. + /// + /// \param Member the name of the member that we are referring to. In C, + /// this will always store an identifier; in C++, we may also have operator + /// names, conversion function names, destructors, and template names. + /// + /// \param ObjCImpDecl the Objective-C implementation declaration. + /// FIXME: Do we really need this? + /// + /// \param HasTrailingLParen whether this member name is immediately followed + /// by a left parentheses ('('). + virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &Member, + DeclPtrTy ObjCImpDecl, + bool HasTrailingLParen) { + return ExprEmpty(); + } + + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. There are guaranteed to be one fewer commas than arguments, + /// unless there are zero arguments. + virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + // Unary Operators. 'Tok' is the token for the operator. + virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Op, ExprArg Input) { + return ExprEmpty(); + } + virtual OwningExprResult + ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, + void *TyOrEx, const SourceRange &ArgRange) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen, + TypeTy *Ty, + SourceLocation RParen, + ExprArg Op) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc, + MultiExprArg InitList, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + /// @brief Parsed a C99 designated initializer. + /// + /// @param Desig Contains the designation with one or more designators. + /// + /// @param Loc The location of the '=' or ':' prior to the + /// initialization expression. + /// + /// @param GNUSyntax If true, then this designated initializer used + /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather + /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo. + /// + /// @param Init The value that the entity (or entities) described by + /// the designation will be initialized with. + virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool GNUSyntax, + OwningExprResult Init) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + TypeTy *Ty, SourceLocation RParenLoc, + ExprArg Op) { + return ExprEmpty(); + } + + virtual bool TypeIsVectorType(TypeTy *Ty) { + return false; + } + + virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, + ExprArg LHS, ExprArg RHS) { + return ExprEmpty(); + } + + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null + /// in the case of a the GNU conditional expr extension. + virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, + ExprArg Cond, ExprArg LHS, + ExprArg RHS) { + return ExprEmpty(); + } + + //===---------------------- GNU Extension Expressions -------------------===// + + virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc, + SourceLocation LabLoc, + IdentifierInfo *LabelII) { // "&&foo" + return ExprEmpty(); + } + + virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt, + SourceLocation RPLoc) { // "({..})" + return ExprEmpty(); + } + + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + struct OffsetOfComponent { + SourceLocation LocStart, LocEnd; + bool isBrackets; // true if [expr], false if .ident + union { + IdentifierInfo *IdentInfo; + ExprTy *E; + } U; + }; + + virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S, + SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + TypeTy *Arg1, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + // __builtin_types_compatible_p(type1, type2) + virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, + TypeTy *arg1, TypeTy *arg2, + SourceLocation RPLoc) { + return ExprEmpty(); + } + // __builtin_choose_expr(constExpr, expr1, expr2) + virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, + ExprArg cond, ExprArg expr1, + ExprArg expr2, SourceLocation RPLoc){ + return ExprEmpty(); + } + + // __builtin_va_arg(expr, type) + virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc, + ExprArg expr, TypeTy *type, + SourceLocation RPLoc) { + return ExprEmpty(); + } + + /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token + /// for which is at position TokenLoc. + virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) { + return ExprEmpty(); + } + + //===------------------------- "Block" Extension ------------------------===// + + /// ActOnBlockStart - This callback is invoked when a block literal is + /// started. The result pointer is passed into the block finalizers. + virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {} + + /// ActOnBlockArguments - This callback allows processing of block arguments. + /// If there are no arguments, this is still invoked. + virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {} + + /// ActOnBlockError - If there is an error parsing a block, this callback + /// is invoked to pop the information about the block from the action impl. + virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {} + + /// ActOnBlockStmtExpr - This is called when the body of a block statement + /// literal was successfully completed. ^(int x){...} + virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, + StmtArg Body, + Scope *CurScope) { + return ExprEmpty(); + } + + //===------------------------- C++ Declarations -------------------------===// + + /// ActOnStartNamespaceDef - This is called at the start of a namespace + /// definition. + virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, + IdentifierInfo *Ident, + SourceLocation LBrace, + AttributeList *AttrList) { + return DeclPtrTy(); + } + + /// ActOnFinishNamespaceDef - This callback is called after a namespace is + /// exited. Decl is returned by ActOnStartNamespaceDef. + virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) { + return; + } + + /// ActOnUsingDirective - This is called when using-directive is parsed. + virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, + SourceLocation UsingLoc, + SourceLocation NamespcLoc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + AttributeList *AttrList); + + /// ActOnNamespaceAliasDef - This is called when a namespace alias definition + /// is parsed. + virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + return DeclPtrTy(); + } + + /// \brief Parsed a C++ using-declaration. + /// + /// This callback will be invoked when the parser has parsed a C++ + /// using-declaration, e.g., + /// + /// \code + /// namespace std { + /// template<typename T, typename Alloc> class vector; + /// } + /// + /// using std::vector; // using-declaration here + /// \endcode + /// + /// \param CurScope the scope in which this using declaration was parsed. + /// + /// \param AS the currently-active access specifier. + /// + /// \param HasUsingKeyword true if this was declared with an + /// explicit 'using' keyword (i.e. if this is technically a using + /// declaration, not an access declaration) + /// + /// \param UsingLoc the location of the 'using' keyword. + /// + /// \param SS the nested-name-specifier that precedes the name. + /// + /// \param Name the name to which the using declaration refers. + /// + /// \param AttrList attributes applied to this using declaration, if any. + /// + /// \param IsTypeName whether this using declaration started with the + /// 'typename' keyword. FIXME: This will eventually be split into a + /// separate action. + /// + /// \param TypenameLoc the location of the 'typename' keyword, if present + /// + /// \returns a representation of the using declaration. + virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, + AccessSpecifier AS, + bool HasUsingKeyword, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + AttributeList *AttrList, + bool IsTypeName, + SourceLocation TypenameLoc); + + /// ActOnParamDefaultArgument - Parse default argument for function parameter + virtual void ActOnParamDefaultArgument(DeclPtrTy param, + SourceLocation EqualLoc, + ExprArg defarg) { + } + + /// ActOnParamUnparsedDefaultArgument - We've seen a default + /// argument for a function parameter, but we can't parse it yet + /// because we're inside a class definition. Note that this default + /// argument will be parsed later. + virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param, + SourceLocation EqualLoc, + SourceLocation ArgLoc) { } + + /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of + /// the default argument for the parameter param failed. + virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { } + + /// AddCXXDirectInitializerToDecl - This action is called immediately after + /// ActOnDeclarator, when a C++ direct initializer is present. + /// e.g: "int x(1);" + virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return; + } + + /// \brief Called when we re-enter a template parameter scope. + /// + /// This action occurs when we are going to parse an member + /// function's default arguments or inline definition after the + /// outermost class definition has been completed, and when one or + /// more of the class definitions enclosing the member function is a + /// template. The "entity" in the given scope will be set as it was + /// when we entered the scope of the template initially, and should + /// be used to, e.g., reintroduce the names of template parameters + /// into the current scope so that they can be found by name lookup. + /// + /// \param S The (new) template parameter scope. + /// + /// \param Template the class template declaration whose template + /// parameters should be reintroduced into the current scope. + virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) { + } + + /// ActOnStartDelayedMemberDeclarations - We have completed parsing + /// a C++ class, and we are about to start parsing any parts of + /// member declarations that could not be parsed earlier. Enter + /// the appropriate record scope. + virtual void ActOnStartDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record) { + } + + /// ActOnStartDelayedCXXMethodDeclaration - We have completed + /// parsing a top-level (non-nested) C++ class, and we are now + /// parsing those parts of the given Method declaration that could + /// not be parsed earlier (C++ [class.mem]p2), such as default + /// arguments. This action should enter the scope of the given + /// Method declaration as if we had just parsed the qualified method + /// name. However, it should not bring the parameters into scope; + /// that will be performed by ActOnDelayedCXXMethodParameter. + virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, + DeclPtrTy Method) { + } + + /// ActOnDelayedCXXMethodParameter - We've already started a delayed + /// C++ method declaration. We're (re-)introducing the given + /// function parameter into scope for use in parsing later parts of + /// the method declaration. For example, we could see an + /// ActOnParamDefaultArgument event for this parameter. + virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) { + } + + /// ActOnFinishDelayedCXXMethodDeclaration - We have finished + /// processing the delayed method declaration for Method. The method + /// declaration is now considered finished. There may be a separate + /// ActOnStartOfFunctionDef action later (not necessarily + /// immediately!) for this method, if it was also defined inside the + /// class body. + virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, + DeclPtrTy Method) { + } + + /// ActOnFinishDelayedMemberDeclarations - We have finished parsing + /// a C++ class, and we are about to start parsing any parts of + /// member declarations that could not be parsed earlier. Enter the + /// appropriate record scope. + virtual void ActOnFinishDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record) { + } + + /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration. + virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + ExprArg AssertExpr, + ExprArg AssertMessageExpr) { + return DeclPtrTy(); + } + + /// ActOnFriendFunctionDecl - Parsed a friend function declarator. + /// The name is actually a slight misnomer, because the declarator + /// is not necessarily a function declarator. + virtual DeclPtrTy ActOnFriendFunctionDecl(Scope *S, + Declarator &D, + bool IsDefinition, + MultiTemplateParamsArg TParams) { + return DeclPtrTy(); + } + + /// ActOnFriendTypeDecl - Parsed a friend type declaration. + virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, + MultiTemplateParamsArg TParams) { + return DeclPtrTy(); + } + + //===------------------------- C++ Expressions --------------------------===// + + /// \brief Parsed a destructor name or pseudo-destructor name. + /// + /// \returns the type being destructed. + virtual TypeTy *getDestructorName(SourceLocation TildeLoc, + IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + TypeTy *ObjectType, + bool EnteringContext) { + return getTypeName(II, NameLoc, S, &SS, false, ObjectType); + } + + + /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. + virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc, + tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, + TypeTy *Ty, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, + ExprArg Op, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// ActOnCXXTypeidOfType - Parse typeid( type-id ). + virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc, + SourceLocation LParenLoc, bool isType, + void *TyOrExpr, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// ActOnCXXThis - Parse the C++ 'this' pointer. + virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) { + return ExprEmpty(); + } + + /// ActOnCXXBoolLiteral - Parse {true,false} literals. + virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, + tok::TokenKind Kind) { + return ExprEmpty(); + } + + /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. + virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) { + return ExprEmpty(); + } + + /// ActOnCXXThrow - Parse throw expressions. + virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) { + return ExprEmpty(); + } + + /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. + /// Can be interpreted either as function-style casting ("int(x)") + /// or class type construction ("ClassType(x,y,z)") + /// or creation of a value-initialized type ("int()"). + virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, + TypeTy *TypeRep, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// \brief Parsed a condition declaration in a C++ if, switch, or while + /// statement. + /// + /// This callback will be invoked after parsing the declaration of "x" in + /// + /// \code + /// if (int x = f()) { + /// // ... + /// } + /// \endcode + /// + /// \param S the scope of the if, switch, or while statement. + /// + /// \param D the declarator that that describes the variable being declared. + virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { + return DeclResult(); + } + + /// \brief Parsed an expression that will be handled as the condition in + /// an if/while/for statement. + /// + /// This routine handles the conversion of the expression to 'bool'. + /// + /// \param S The scope in which the expression occurs. + /// + /// \param Loc The location of the construct that requires the conversion to + /// a boolean value. + /// + /// \param SubExpr The expression that is being converted to bool. + virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, + ExprArg SubExpr) { + return move(SubExpr); + } + + /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the + /// new was qualified (::new). In a full new like + /// @code new (p1, p2) type(c1, c2) @endcode + /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2 + /// expressions in ConstructorArgs. The type is passed as a declarator. + virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + bool ParenTypeId, Declarator &D, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen) { + return ExprEmpty(); + } + + /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if + /// the delete was qualified (::delete). ArrayForm is true if the array form + /// was used (delete[]). + virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, + bool UseGlobal, bool ArrayForm, + ExprArg Operand) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, + SourceLocation KWLoc, + SourceLocation LParen, + TypeTy *Ty, + SourceLocation RParen) { + return ExprEmpty(); + } + + /// \brief Invoked when the parser is starting to parse a C++ member access + /// expression such as x.f or x->f. + /// + /// \param S the scope in which the member access expression occurs. + /// + /// \param Base the expression in which a member is being accessed, e.g., the + /// "x" in "x.f". + /// + /// \param OpLoc the location of the member access operator ("." or "->") + /// + /// \param OpKind the kind of member access operator ("." or "->") + /// + /// \param ObjectType originally NULL. The action should fill in this type + /// with the type into which name lookup should look to find the member in + /// the member access expression. + /// + /// \param MayBePseudoDestructor Originally false. The action should + /// set this true if the expression may end up being a + /// pseudo-destructor expression, indicating to the parser that it + /// shoudl be parsed as a pseudo-destructor rather than as a member + /// access expression. Note that this should apply both when the + /// object type is a scalar and when the object type is dependent. + /// + /// \returns the (possibly modified) \p Base expression + virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S, + ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + TypeTy *&ObjectType, + bool &MayBePseudoDestructor) { + return ExprEmpty(); + } + + /// \brief Parsed a C++ pseudo-destructor expression or a dependent + /// member access expression that has the same syntactic form as a + /// pseudo-destructor expression. + /// + /// \param S The scope in which the member access expression occurs. + /// + /// \param Base The expression in which a member is being accessed, e.g., the + /// "x" in "x.f". + /// + /// \param OpLoc The location of the member access operator ("." or "->") + /// + /// \param OpKind The kind of member access operator ("." or "->") + /// + /// \param SS The nested-name-specifier that precedes the type names + /// in the grammar. Note that this nested-name-specifier will not + /// cover the last "type-name ::" in the grammar, because it isn't + /// necessarily a nested-name-specifier. + /// + /// \param FirstTypeName The type name that follows the optional + /// nested-name-specifier but precedes the '::', e.g., the first + /// type-name in "type-name :: type-name". This type name may be + /// empty. This will be either an identifier or a template-id. + /// + /// \param CCLoc The location of the '::' in "type-name :: + /// typename". May be invalid, if there is no \p FirstTypeName. + /// + /// \param TildeLoc The location of the '~'. + /// + /// \param SecondTypeName The type-name following the '~', which is + /// the name of the type being destroyed. This will be either an + /// identifier or a template-id. + /// + /// \param HasTrailingLParen Whether the next token in the stream is + /// a left parentheses. + virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen) { + return ExprEmpty(); + } + + /// ActOnFinishFullExpr - Called whenever a full expression has been parsed. + /// (C++ [intro.execution]p12). + virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) { + return move(Expr); + } + + //===---------------------------- C++ Classes ---------------------------===// + /// ActOnBaseSpecifier - Parsed a base specifier + virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeTy *basetype, + SourceLocation BaseLoc) { + return BaseResult(); + } + + virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, + unsigned NumBases) { + } + + /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member + /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth' + /// specifies the bitfield width if there is one and 'Init' specifies the + /// initializer if any. 'Deleted' is true if there's a =delete + /// specifier on the function. + virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, + Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + ExprTy *BitfieldWidth, + ExprTy *Init, + bool IsDefinition, + bool Deleted = false) { + return DeclPtrTy(); + } + + virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, + SourceLocation IdLoc, + SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return true; + } + + /// ActOnMemInitializers - This is invoked when all of the member + /// initializers of a constructor have been parsed. ConstructorDecl + /// is the function declaration (which will be a C++ constructor in + /// a well-formed program), ColonLoc is the location of the ':' that + /// starts the constructor initializer, and MemInit/NumMemInits + /// contains the individual member (and base) initializers. + /// AnyErrors will be true if there were any invalid member initializers + /// that are not represented in the list. + virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, + SourceLocation ColonLoc, + MemInitTy **MemInits, unsigned NumMemInits, + bool AnyErrors){ + } + + virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {} + + /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators + /// are parsed but *before* parsing of inline method definitions. + virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, + DeclPtrTy TagDecl, + SourceLocation LBrac, + SourceLocation RBrac, + AttributeList *AttrList) { + } + + //===---------------------------C++ Templates----------------------------===// + + /// ActOnTypeParameter - Called when a C++ template type parameter + /// (e.g., "typename T") has been parsed. Typename specifies whether + /// the keyword "typename" was used to declare the type parameter + /// (otherwise, "class" was used), ellipsis specifies whether this is a + /// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis, + /// and KeyLoc is the location of the "class" or "typename" keyword. + // ParamName is the name of the parameter (NULL indicates an unnamed template + // parameter) and ParamNameLoc is the location of the parameter name (if any) + /// If the type parameter has a default argument, it will be added + /// later via ActOnTypeParameterDefault. Depth and Position provide + /// the number of enclosing templates (see + /// ActOnTemplateParameterList) and the number of previous + /// parameters within this template parameter list. + virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position) { + return DeclPtrTy(); + } + + /// ActOnTypeParameterDefault - Adds a default argument (the type + /// Default) to the given template type parameter (TypeParam). + virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam, + SourceLocation EqualLoc, + SourceLocation DefaultLoc, + TypeTy *Default) { + } + + /// ActOnNonTypeTemplateParameter - Called when a C++ non-type + /// template parameter (e.g., "int Size" in "template<int Size> + /// class Array") has been parsed. S is the current scope and D is + /// the parsed declarator. Depth and Position provide the number of + /// enclosing templates (see + /// ActOnTemplateParameterList) and the number of previous + /// parameters within this template parameter list. + virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position) { + return DeclPtrTy(); + } + + /// \brief Adds a default argument to the given non-type template + /// parameter. + virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam, + SourceLocation EqualLoc, + ExprArg Default) { + } + + /// ActOnTemplateTemplateParameter - Called when a C++ template template + /// parameter (e.g., "int T" in "template<template <typename> class T> class + /// Array") has been parsed. TmpLoc is the location of the "template" keyword, + /// TemplateParams is the sequence of parameters required by the template, + /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc + /// is the source location of the identifier (if given). + virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position) { + return DeclPtrTy(); + } + + /// \brief Adds a default argument to the given template template + /// parameter. + virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, + SourceLocation EqualLoc, + const ParsedTemplateArgument &Default) { + } + + /// ActOnTemplateParameterList - Called when a complete template + /// parameter list has been parsed, e.g., + /// + /// @code + /// export template<typename T, T Size> + /// @endcode + /// + /// Depth is the number of enclosing template parameter lists. This + /// value does not include templates from outer scopes. For example: + /// + /// @code + /// template<typename T> // depth = 0 + /// class A { + /// template<typename U> // depth = 0 + /// class B; + /// }; + /// + /// template<typename T> // depth = 0 + /// template<typename U> // depth = 1 + /// class A<T>::B { ... }; + /// @endcode + /// + /// ExportLoc, if valid, is the position of the "export" + /// keyword. Otherwise, "export" was not specified. + /// TemplateLoc is the position of the template keyword, LAngleLoc + /// is the position of the left angle bracket, and RAngleLoc is the + /// position of the corresponding right angle bracket. + /// Params/NumParams provides the template parameters that were + /// parsed as part of the template-parameter-list. + virtual TemplateParamsTy * + ActOnTemplateParameterList(unsigned Depth, + SourceLocation ExportLoc, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + DeclPtrTy *Params, unsigned NumParams, + SourceLocation RAngleLoc) { + return 0; + } + + /// \brief Form a type from a template and a list of template + /// arguments. + /// + /// This action merely forms the type for the template-id, possibly + /// checking well-formedness of the template arguments. It does not + /// imply the declaration of any entity. + /// + /// \param Template A template whose specialization results in a + /// type, e.g., a class template or template template parameter. + virtual TypeResult ActOnTemplateIdType(TemplateTy Template, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc) { + return TypeResult(); + } + + /// \brief Note that a template ID was used with a tag. + /// + /// \param Type The result of ActOnTemplateIdType. + /// + /// \param TUK Either TUK_Reference or TUK_Friend. Declarations and + /// definitions are interpreted as explicit instantiations or + /// specializations. + /// + /// \param TagSpec The tag keyword that was provided as part of the + /// elaborated-type-specifier; either class, struct, union, or enum. + /// + /// \param TagLoc The location of the tag keyword. + virtual TypeResult ActOnTagTemplateIdType(TypeResult Type, + TagUseKind TUK, + DeclSpec::TST TagSpec, + SourceLocation TagLoc) { + return TypeResult(); + } + + /// \brief Form a dependent template name. + /// + /// This action forms a dependent template name given the template + /// name and its (presumably dependent) scope specifier. For + /// example, given "MetaFun::template apply", the scope specifier \p + /// SS will be "MetaFun::", \p TemplateKWLoc contains the location + /// of the "template" keyword, and "apply" is the \p Name. + /// + /// \param TemplateKWLoc the location of the "template" keyword (if any). + /// + /// \param SS the nested-name-specifier that precedes the "template" keyword + /// or the template name. If the dependent template name occurs in + /// a member access expression, e.g., "x.template f<T>", this + /// nested-name-specifier will be empty. + /// + /// \param Name the name of the template. + /// + /// \param ObjectType if this dependent template name occurs in the + /// context of a member access expression, the type of the object being + /// accessed. + /// + /// \param EnteringContext whether we are entering the context of this + /// template. + virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext) { + return TemplateTy(); + } + + /// \brief Process the declaration or definition of an explicit + /// class template specialization or a class template partial + /// specialization. + /// + /// This routine is invoked when an explicit class template + /// specialization or a class template partial specialization is + /// declared or defined, to introduce the (partial) specialization + /// and produce a declaration for it. In the following example, + /// ActOnClassTemplateSpecialization will be invoked for the + /// declarations at both A and B: + /// + /// \code + /// template<typename T> class X; + /// template<> class X<int> { }; // A: explicit specialization + /// template<typename T> class X<T*> { }; // B: partial specialization + /// \endcode + /// + /// Note that it is the job of semantic analysis to determine which + /// of the two cases actually occurred in the source code, since + /// they are parsed through the same path. The formulation of the + /// template parameter lists describes which case we are in. + /// + /// \param S the current scope + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template) + /// + /// \param TUK whether this is a declaration or a definition + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id + /// + /// \param Template the declaration of the class template that we + /// are specializing. + /// + /// \param Attr attributes on the specialization + /// + /// \param TemplateParameterLists the set of template parameter + /// lists that apply to this declaration. In a well-formed program, + /// the number of template parameter lists will be one more than the + /// number of template-ids in the scope specifier. However, it is + /// common for users to provide the wrong number of template + /// parameter lists (such as a missing \c template<> prior to a + /// specialization); the parser does not check this condition. + virtual DeclResult + ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, + AttributeList *Attr, + MultiTemplateParamsArg TemplateParameterLists) { + return DeclResult(); + } + + /// \brief Invoked when a declarator that has one or more template parameter + /// lists has been parsed. + /// + /// This action is similar to ActOnDeclarator(), except that the declaration + /// being created somehow involves a template, e.g., it is a template + /// declaration or specialization. + virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + return DeclPtrTy(); + } + + /// \brief Invoked when the parser is beginning to parse a function template + /// or function template specialization definition. + virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + return DeclPtrTy(); + } + + /// \brief Process the explicit instantiation of a class template + /// specialization. + /// + /// This routine is invoked when an explicit instantiation of a + /// class template specialization is encountered. In the following + /// example, ActOnExplicitInstantiation will be invoked to force the + /// instantiation of X<int>: + /// + /// \code + /// template<typename T> class X { /* ... */ }; + /// template class X<int>; // explicit instantiation + /// \endcode + /// + /// \param S the current scope + /// + /// \param ExternLoc the location of the 'extern' keyword that specifies that + /// this is an extern template (if any). + /// + /// \param TemplateLoc the location of the 'template' keyword that + /// specifies that this is an explicit instantiation. + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template). + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id. + /// + /// \param Template the declaration of the class template that we + /// are instantiation. + /// + /// \param LAngleLoc the location of the '<' token in the template-id. + /// + /// \param TemplateArgs the template arguments used to form the + /// template-id. + /// + /// \param TemplateArgLocs the locations of the template arguments. + /// + /// \param RAngleLoc the location of the '>' token in the template-id. + /// + /// \param Attr attributes that apply to this instantiation. + virtual DeclResult + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, + AttributeList *Attr) { + return DeclResult(); + } + + /// \brief Process the explicit instantiation of a member class of a + /// class template specialization. + /// + /// This routine is invoked when an explicit instantiation of a + /// member class of a class template specialization is + /// encountered. In the following example, + /// ActOnExplicitInstantiation will be invoked to force the + /// instantiation of X<int>::Inner: + /// + /// \code + /// template<typename T> class X { class Inner { /* ... */}; }; + /// template class X<int>::Inner; // explicit instantiation + /// \endcode + /// + /// \param S the current scope + /// + /// \param ExternLoc the location of the 'extern' keyword that specifies that + /// this is an extern template (if any). + /// + /// \param TemplateLoc the location of the 'template' keyword that + /// specifies that this is an explicit instantiation. + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template). + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id. + /// + /// \param Template the declaration of the class template that we + /// are instantiation. + /// + /// \param LAngleLoc the location of the '<' token in the template-id. + /// + /// \param TemplateArgs the template arguments used to form the + /// template-id. + /// + /// \param TemplateArgLocs the locations of the template arguments. + /// + /// \param RAngleLoc the location of the '>' token in the template-id. + /// + /// \param Attr attributes that apply to this instantiation. + virtual DeclResult + ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr) { + return DeclResult(); + } + + /// \brief Process the explicit instantiation of a function template or a + /// member of a class template. + /// + /// This routine is invoked when an explicit instantiation of a + /// function template or member function of a class template specialization + /// is encountered. In the following example, + /// ActOnExplicitInstantiation will be invoked to force the + /// instantiation of X<int>: + /// + /// \code + /// template<typename T> void f(T); + /// template void f(int); // explicit instantiation + /// \endcode + /// + /// \param S the current scope + /// + /// \param ExternLoc the location of the 'extern' keyword that specifies that + /// this is an extern template (if any). + /// + /// \param TemplateLoc the location of the 'template' keyword that + /// specifies that this is an explicit instantiation. + /// + /// \param D the declarator describing the declaration to be implicitly + /// instantiated. + virtual DeclResult ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + Declarator &D) { + return DeclResult(); + } + + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in an identifier, e.g., "typename T::type". + /// + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param II the identifier we're retrieving (e.g., 'type' in the example). + /// \param IdLoc the location of the identifier. + virtual TypeResult + ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + const IdentifierInfo &II, SourceLocation IdLoc) { + return TypeResult(); + } + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in a template-id, e.g., + /// "typename MetaFun::template apply<T1, T2>". + /// + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param Ty the type that the typename specifier refers to. + virtual TypeResult + ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + SourceLocation TemplateLoc, TypeTy *Ty) { + return TypeResult(); + } + + //===----------------------- Obj-C Declarations -------------------------===// + + // ActOnStartClassInterface - this action is called immediately after parsing + // the prologue for a class interface (before parsing the instance + // variables). Instance variables are processed by ActOnFields(). + virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperName, + SourceLocation SuperLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + return DeclPtrTy(); + } + + /// ActOnCompatiblityAlias - this action is called after complete parsing of + /// @compaatibility_alias declaration. It sets up the alias relationships. + virtual DeclPtrTy ActOnCompatiblityAlias( + SourceLocation AtCompatibilityAliasLoc, + IdentifierInfo *AliasName, SourceLocation AliasLocation, + IdentifierInfo *ClassName, SourceLocation ClassLocation) { + return DeclPtrTy(); + } + + // ActOnStartProtocolInterface - this action is called immdiately after + // parsing the prologue for a protocol interface. + virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc, + IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + return DeclPtrTy(); + } + // ActOnStartCategoryInterface - this action is called immdiately after + // parsing the prologue for a category interface. + virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CategoryName, + SourceLocation CategoryLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc) { + return DeclPtrTy(); + } + // ActOnStartClassImplementation - this action is called immdiately after + // parsing the prologue for a class implementation. Instance variables are + // processed by ActOnFields(). + virtual DeclPtrTy ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc) { + return DeclPtrTy(); + } + // ActOnStartCategoryImplementation - this action is called immdiately after + // parsing the prologue for a category implementation. + virtual DeclPtrTy ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CatName, + SourceLocation CatLoc) { + return DeclPtrTy(); + } + // ActOnPropertyImplDecl - called for every property implementation + virtual DeclPtrTy ActOnPropertyImplDecl( + Scope *S, + SourceLocation AtLoc, // location of the @synthesize/@dynamic + SourceLocation PropertyNameLoc, // location for the property name + bool ImplKind, // true for @synthesize, false for + // @dynamic + DeclPtrTy ClassImplDecl, // class or category implementation + IdentifierInfo *propertyId, // name of property + IdentifierInfo *propertyIvar) { // name of the ivar + return DeclPtrTy(); + } + + struct ObjCArgInfo { + IdentifierInfo *Name; + SourceLocation NameLoc; + // The Type is null if no type was specified, and the DeclSpec is invalid + // in this case. + TypeTy *Type; + ObjCDeclSpec DeclSpec; + + /// ArgAttrs - Attribute list for this argument. + AttributeList *ArgAttrs; + }; + + // ActOnMethodDeclaration - called for all method declarations. + virtual DeclPtrTy ActOnMethodDeclaration( + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class. + DeclPtrTy ClassDecl, // class this methods belongs to. + ObjCDeclSpec &ReturnQT, // for return type's in inout etc. + TypeTy *ReturnType, // the method return type. + Selector Sel, // a unique name for the method. + ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries. + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args + AttributeList *MethodAttrList, // optional + // tok::objc_not_keyword, tok::objc_optional, tok::objc_required + tok::ObjCKeywordKind impKind, + bool isVariadic = false) { + return DeclPtrTy(); + } + // ActOnAtEnd - called to mark the @end. For declarations (interfaces, + // protocols, categories), the parser passes all methods/properties. + // For class implementations, these values default to 0. For implementations, + // methods are processed incrementally (by ActOnMethodDeclaration above). + virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd, + DeclPtrTy classDecl, + DeclPtrTy *allMethods = 0, + unsigned allNum = 0, + DeclPtrTy *allProperties = 0, + unsigned pNum = 0, + DeclGroupPtrTy *allTUVars = 0, + unsigned tuvNum = 0) { + } + // ActOnProperty - called to build one property AST + virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, + FieldDeclarator &FD, ObjCDeclSpec &ODS, + Selector GetterSel, Selector SetterSel, + DeclPtrTy ClassCategory, + bool *OverridingProperty, + tok::ObjCKeywordKind MethodImplKind) { + return DeclPtrTy(); + } + + virtual OwningExprResult + ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc) { + return ExprEmpty(); + } + + /// \brief Describes the kind of message expression indicated by a message + /// send that starts with an identifier. + enum ObjCMessageKind { + /// \brief The message is sent to 'super'. + ObjCSuperMessage, + /// \brief The message is an instance message. + ObjCInstanceMessage, + /// \brief The message is a class message, and the identifier is a type + /// name. + ObjCClassMessage + }; + + /// \brief Determine the kind of Objective-C message send that we will be + /// performing based on the identifier given. + /// + /// This action determines how a message send that starts with [ + /// identifier (followed by another identifier) will be parsed, + /// e.g., as a class message, instance message, super message. The + /// result depends on the meaning of the given identifier. If the + /// identifier is unknown, the action should indicate that the + /// message is an instance message. + /// + /// By default, this routine applies syntactic disambiguation and uses + /// \c getTypeName() to determine whether the identifier refers to a type. + /// However, \c Action subclasses may override this routine to improve + /// error recovery. + /// + /// \param S The scope in which the message send occurs. + /// + /// \param Name The identifier following the '['. + /// + /// \param NameLoc The location of the identifier. + /// + /// \param IsSuper Whether the name is the pseudo-keyword "super". + /// + /// \param HasTrailingDot Whether the name is followed by a period. + /// + /// \param ReceiverType If this routine returns \c ObjCClassMessage, + /// this argument will be set to the receiver type. + /// + /// \returns The kind of message send. + virtual ObjCMessageKind getObjCMessageKind(Scope *S, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsSuper, + bool HasTrailingDot, + TypeTy *&ReceiverType); + + /// \brief Parsed a message send to 'super'. + /// + /// \param S The scope in which the message send occurs. + /// \param SuperLoc The location of the 'super' keyword. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); + } + + /// \brief Parsed a message send to a class. + /// + /// \param S The scope in which the message send occurs. + /// \param Receiver The type of the class receiving the message. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnClassMessage(Scope *S, + TypeTy *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); + } + + /// \brief Parsed a message send to an object instance. + /// + /// \param S The scope in which the message send occurs. + /// \param Receiver The expression that computes the receiver object. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnInstanceMessage(Scope *S, + ExprArg Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); + } + + virtual DeclPtrTy ActOnForwardClassDeclaration( + SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts) { + return DeclPtrTy(); + } + virtual DeclPtrTy ActOnForwardProtocolDeclaration( + SourceLocation AtProtocolLoc, + const IdentifierLocPair*IdentList, + unsigned NumElts, + AttributeList *AttrList) { + return DeclPtrTy(); + } + + /// FindProtocolDeclaration - This routine looks up protocols and + /// issues error if they are not declared. It returns list of valid + /// protocols found. + virtual void FindProtocolDeclaration(bool WarnOnDeclarations, + const IdentifierLocPair *ProtocolId, + unsigned NumProtocols, + llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) { + } + + //===----------------------- Obj-C Expressions --------------------------===// + + virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, + ExprTy **Strings, + unsigned NumStrings) { + return ExprResult(); + } + + virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncLoc, + SourceLocation LParenLoc, + TypeTy *Ty, + SourceLocation RParenLoc) { + return ExprResult(); + } + + virtual ExprResult ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return ExprResult(); + } + + virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return ExprResult(); + } + + //===---------------------------- Pragmas -------------------------------===// + + enum PragmaOptionsAlignKind { + POAK_Natural, // #pragma options align=natural + POAK_Power, // #pragma options align=power + POAK_Mac68k, // #pragma options align=mac68k + POAK_Reset // #pragma options align=reset + }; + + /// ActOnPragmaOptionsAlign - Called on well formed #pragma options + /// align={...}. + virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc, + SourceLocation KindLoc) { + return; + } + + enum PragmaPackKind { + PPK_Default, // #pragma pack([n]) + PPK_Show, // #pragma pack(show), only supported by MSVC. + PPK_Push, // #pragma pack(push, [identifier], [n]) + PPK_Pop // #pragma pack(pop, [identifier], [n]) + }; + + /// ActOnPragmaPack - Called on well formed #pragma pack(...). + virtual void ActOnPragmaPack(PragmaPackKind Kind, + IdentifierInfo *Name, + ExprTy *Alignment, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return; + } + + /// ActOnPragmaUnused - Called on well formed #pragma unused(...). + virtual void ActOnPragmaUnused(const Token *Identifiers, + unsigned NumIdentifiers, Scope *CurScope, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return; + } + + /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. + virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc) { + return; + } + + /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. + virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc) { + return; + } + + /// \name Code completion actions + /// + /// These actions are used to signal that a code-completion token has been + /// found at a point in the grammar where the Action implementation is + /// likely to be able to provide a list of possible completions, e.g., + /// after the "." or "->" of a member access expression. + /// + /// \todo Code completion for designated field initializers + /// \todo Code completion for call arguments after a function template-id + /// \todo Code completion within a call expression, object construction, etc. + /// \todo Code completion within a template argument list. + /// \todo Code completion for attributes. + //@{ + + /// \brief Describes the context in which code completion occurs. + enum CodeCompletionContext { + /// \brief Code completion occurs at top-level or namespace context. + CCC_Namespace, + /// \brief Code completion occurs within a class, struct, or union. + CCC_Class, + /// \brief Code completion occurs within an Objective-C interface, protocol, + /// or category. + CCC_ObjCInterface, + /// \brief Code completion occurs within an Objective-C implementation or + /// category implementation + CCC_ObjCImplementation, + /// \brief Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + CCC_ObjCInstanceVariableList, + /// \brief Code completion occurs following one or more template + /// headers. + CCC_Template, + /// \brief Code completion occurs following one or more template + /// headers within a class. + CCC_MemberTemplate, + /// \brief Code completion occurs within an expression. + CCC_Expression, + /// \brief Code completion occurs within a statement, which may + /// also be an expression or a declaration. + CCC_Statement, + /// \brief Code completion occurs at the beginning of the + /// initialization statement (or expression) in a for loop. + CCC_ForInit, + /// \brief Code completion occurs within the condition of an if, + /// while, switch, or for statement. + CCC_Condition, + /// \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. + CCC_RecoveryInFunction + }; + + /// \brief Code completion for an ordinary name that occurs within the given + /// scope. + /// + /// \param S the scope in which the name occurs. + /// + /// \param CompletionContext the context in which code completion + /// occurs. + virtual void CodeCompleteOrdinaryName(Scope *S, + CodeCompletionContext CompletionContext) { } + + /// \brief Code completion for a member access expression. + /// + /// This code completion action is invoked when the code-completion token + /// is found after the "." or "->" of a member access expression. + /// + /// \param S the scope in which the member access expression occurs. + /// + /// \param Base the base expression (e.g., the x in "x.foo") of the member + /// access. + /// + /// \param OpLoc the location of the "." or "->" operator. + /// + /// \param IsArrow true when the operator is "->", false when it is ".". + virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, + SourceLocation OpLoc, + bool IsArrow) { } + + /// \brief Code completion for a reference to a tag. + /// + /// This code completion action is invoked when the code-completion + /// token is found after a tag keyword (struct, union, enum, or class). + /// + /// \param S the scope in which the tag reference occurs. + /// + /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag + /// this is (struct/union/enum/class). + virtual void CodeCompleteTag(Scope *S, unsigned TagSpec) { } + + /// \brief Code completion for a case statement. + /// + /// \brief S the scope in which the case statement occurs. + virtual void CodeCompleteCase(Scope *S) { } + + /// \brief Code completion for a call. + /// + /// \brief S the scope in which the call occurs. + /// + /// \param Fn the expression describing the function being called. + /// + /// \param Args the arguments to the function call (so far). + /// + /// \param NumArgs the number of arguments in \p Args. + virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, + ExprTy **Args, unsigned NumArgs) { } + + /// \brief Code completion for a C++ nested-name-specifier that precedes a + /// qualified-id of some form. + /// + /// This code completion action is invoked when the code-completion token + /// is found after the "::" of a nested-name-specifier. + /// + /// \param S the scope in which the nested-name-specifier occurs. + /// + /// \param SS the scope specifier ending with "::". + /// + /// \parame EnteringContext whether we're entering the context of this + /// scope specifier. + virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, + bool EnteringContext) { } + + /// \brief Code completion for a C++ "using" declaration or directive. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the "using" keyword. + /// + /// \param S the scope in which the "using" occurs. + virtual void CodeCompleteUsing(Scope *S) { } + + /// \brief Code completion for a C++ using directive. + /// + /// This code completion action is invoked when the code-completion token is + /// found after "using namespace". + /// + /// \param S the scope in which the "using namespace" occurs. + virtual void CodeCompleteUsingDirective(Scope *S) { } + + /// \brief Code completion for a C++ namespace declaration or namespace + /// alias declaration. + /// + /// This code completion action is invoked when the code-completion token is + /// found after "namespace". + /// + /// \param S the scope in which the "namespace" token occurs. + virtual void CodeCompleteNamespaceDecl(Scope *S) { } + + /// \brief Code completion for a C++ namespace alias declaration. + /// + /// This code completion action is invoked when the code-completion token is + /// found after "namespace identifier = ". + /// + /// \param S the scope in which the namespace alias declaration occurs. + virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { } + + /// \brief Code completion for an operator name. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the keyword "operator". + /// + /// \param S the scope in which the operator keyword occurs. + virtual void CodeCompleteOperatorName(Scope *S) { } + + /// \brief Code completion after the '@' at the top level. + /// + /// \param S the scope in which the '@' occurs. + /// + /// \param ObjCImpDecl the Objective-C implementation or category + /// implementation. + /// + /// \param InInterface whether we are in an Objective-C interface or + /// protocol. + virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, + bool InInterface) { } + + /// \brief Code completion after the '@' in the list of instance variables. + virtual void CodeCompleteObjCAtVisibility(Scope *S) { } + + /// \brief Code completion after the '@' in a statement. + virtual void CodeCompleteObjCAtStatement(Scope *S) { } + + /// \brief Code completion after the '@' in an expression. + virtual void CodeCompleteObjCAtExpression(Scope *S) { } + + /// \brief Code completion for an ObjC property decl. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the left paren. + /// + /// \param S the scope in which the operator keyword occurs. + virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { } + + /// \brief Code completion for the getter of an Objective-C property + /// declaration. + /// + /// This code completion action is invoked when the code-completion + /// token is found after the "getter = " in a property declaration. + /// + /// \param S the scope in which the property is being declared. + /// + /// \param ClassDecl the Objective-C class or category in which the property + /// is being defined. + /// + /// \param Methods the set of methods declared thus far within \p ClassDecl. + /// + /// \param NumMethods the number of methods in \p Methods + virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + } + + /// \brief Code completion for the setter of an Objective-C property + /// declaration. + /// + /// This code completion action is invoked when the code-completion + /// token is found after the "setter = " in a property declaration. + /// + /// \param S the scope in which the property is being declared. + /// + /// \param ClassDecl the Objective-C class or category in which the property + /// is being defined. + /// + /// \param Methods the set of methods declared thus far within \p ClassDecl. + /// + /// \param NumMethods the number of methods in \p Methods + virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + } + + /// \brief Code completion for an ObjC message expression that sends + /// a message to the superclass. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the class name and after each argument. + /// + /// \param S The scope in which the message expression occurs. + /// \param SuperLoc The location of the 'super' keyword. + /// \param SelIdents The identifiers that describe the selector (thus far). + /// \param NumSelIdents The number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } + + /// \brief Code completion for an ObjC message expression that refers to + /// a class method. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the class name and after each argument. + /// + /// \param S The scope in which the message expression occurs. + /// \param Receiver The type of the class that is receiving a message. + /// \param SelIdents The identifiers that describe the selector (thus far). + /// \param NumSelIdents The number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } + + /// \brief Code completion for an ObjC message expression that refers to + /// an instance method. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the receiver expression and after each argument. + /// + /// \param S the scope in which the operator keyword occurs. + /// \param Receiver an expression for the receiver of the message. + /// \param SelIdents the identifiers that describe the selector (thus far). + /// \param NumSelIdents the number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } + + /// \brief Code completion for a list of protocol references in Objective-C, + /// such as P1 and P2 in \c id<P1,P2>. + /// + /// This code completion action is invoked prior to each identifier + /// in the protocol list. + /// + /// \param Protocols the set of protocols that have already been parsed. + /// + /// \param NumProtocols the number of protocols that have already been + /// parsed. + virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols) { } + + /// \brief Code completion for a protocol declaration or definition, after + /// the @protocol but before any identifier. + /// + /// \param S the scope in which the protocol declaration occurs. + virtual void CodeCompleteObjCProtocolDecl(Scope *S) { } + + /// \brief Code completion for an Objective-C interface, after the + /// @interface but before any identifier. + virtual void CodeCompleteObjCInterfaceDecl(Scope *S) { } + + /// \brief Code completion for the superclass of an Objective-C + /// interface, after the ':'. + /// + /// \param S the scope in which the interface declaration occurs. + /// + /// \param ClassName the name of the class being defined. + virtual void CodeCompleteObjCSuperclass(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + } + + /// \brief Code completion for an Objective-C implementation, after the + /// @implementation but before any identifier. + virtual void CodeCompleteObjCImplementationDecl(Scope *S) { } + + /// \brief Code completion for the category name in an Objective-C interface + /// declaration. + /// + /// This code completion action is invoked after the '(' that indicates + /// a category name within an Objective-C interface declaration. + virtual void CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + } + + /// \brief Code completion for the category name in an Objective-C category + /// implementation. + /// + /// This code completion action is invoked after the '(' that indicates + /// the category name within an Objective-C category implementation. + virtual void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + } + + /// \brief Code completion for the property names when defining an + /// Objective-C property. + /// + /// This code completion action is invoked after @synthesize or @dynamic and + /// after each "," within one of those definitions. + virtual void CodeCompleteObjCPropertyDefinition(Scope *S, + DeclPtrTy ObjCImpDecl) { + } + + /// \brief Code completion for the instance variable name that should + /// follow an '=' when synthesizing an Objective-C property. + /// + /// This code completion action is invoked after each '=' that occurs within + /// an @synthesized definition. + virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + DeclPtrTy ObjCImpDecl) { + } + + /// \brief Code completion for an Objective-C method declaration or + /// definition, which may occur within an interface, category, + /// extension, protocol, or implementation thereof (where applicable). + /// + /// This code completion action is invoked after the "-" or "+" that + /// starts a method declaration or definition, and after the return + /// type such a declaration (e.g., "- (id)"). + /// + /// \param S The scope in which the completion occurs. + /// + /// \param IsInstanceMethod Whether this is an instance method + /// (introduced with '-'); otherwise, it's a class method + /// (introduced with '+'). + /// + /// \param ReturnType If non-NULL, the specified return type of the method + /// being declared or defined. + /// + /// \param IDecl The interface, category, protocol, or + /// implementation, or category implementation in which this method + /// declaration or definition occurs. + virtual void CodeCompleteObjCMethodDecl(Scope *S, + bool IsInstanceMethod, + TypeTy *ReturnType, + DeclPtrTy IDecl) { + } + //@} +}; + +/// MinimalAction - Minimal actions are used by light-weight clients of the +/// parser that do not need name resolution or significant semantic analysis to +/// be performed. The actions implemented here are in the form of unresolved +/// identifiers. By using a simpler interface than the SemanticAction class, +/// the parser doesn't have to build complex data structures and thus runs more +/// quickly. +class MinimalAction : public Action { + /// Translation Unit Scope - useful to Objective-C actions that need + /// to lookup file scope declarations in the "ordinary" C decl namespace. + /// For example, user-defined classes, built-in "id" type, etc. + Scope *TUScope; + IdentifierTable &Idents; + Preprocessor &PP; + void *TypeNameInfoTablePtr; +public: + MinimalAction(Preprocessor &pp); + ~MinimalAction(); + + /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to + /// determine whether the name is a typedef or not in this scope. + /// + /// \param II the identifier for which we are performing name lookup + /// + /// \param NameLoc the location of the identifier + /// + /// \param S the scope in which this name lookup occurs + /// + /// \param SS if non-NULL, the C++ scope specifier that precedes the + /// identifier + /// + /// \param isClassName whether this is a C++ class-name production, in + /// which we can end up referring to a member of an unknown specialization + /// that we know (from the grammar) is supposed to be a type. For example, + /// this occurs when deriving from "std::vector<T>::allocator_type", where T + /// is a template parameter. + /// + /// \returns the type referred to by this identifier, or NULL if the type + /// does not name an identifier. + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS, + bool isClassName = false, + TypeTy *ObjectType = 0); + + /// isCurrentClassName - Always returns false, because MinimalAction + /// does not support C++ classes with constructors. + virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S, + const CXXScopeSpec *SS); + + virtual TemplateNameKind isTemplateName(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization); + + + /// ActOnDeclarator - If this is a typedef declarator, we modify the + /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is + /// popped. + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D); + + /// ActOnPopScope - When a scope is popped, if any typedefs are now + /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field. + virtual void ActOnPopScope(SourceLocation Loc, Scope *S); + virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S); + + virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + SourceLocation *SLocs, + unsigned NumElts); + + virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperName, + SourceLocation SuperLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList); +}; + +/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing +/// something related to a virtualized decl, include that virtualized decl in +/// the stack trace. +class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry { + Action::DeclPtrTy TheDecl; + SourceLocation Loc; + Action &Actions; + SourceManager &SM; + const char *Message; +public: + PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L, + Action &actions, SourceManager &sm, + const char *Msg) + : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {} + + virtual void print(llvm::raw_ostream &OS) const; +}; + +/// \brief RAII object that enters a new expression evaluation context. +class EnterExpressionEvaluationContext { + /// \brief The action object. + Action &Actions; + +public: + EnterExpressionEvaluationContext(Action &Actions, + Action::ExpressionEvaluationContext NewContext) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext(NewContext); + } + + ~EnterExpressionEvaluationContext() { + Actions.PopExpressionEvaluationContext(); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Parse/AttributeList.h new file mode 100644 index 0000000..1e6d3ab --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/AttributeList.h @@ -0,0 +1,227 @@ +//===--- AttributeList.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 defines the AttributeList class interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ATTRLIST_H +#define LLVM_CLANG_ATTRLIST_H + +#include "clang/Parse/Ownership.h" +#include "clang/Basic/SourceLocation.h" +#include <cassert> + +namespace clang { + class IdentifierInfo; + class Action; + +/// AttributeList - Represents GCC's __attribute__ declaration. There are +/// 4 forms of this construct...they are: +/// +/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. +/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. +/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. +/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. +/// +class AttributeList { + IdentifierInfo *AttrName; + SourceLocation AttrLoc; + IdentifierInfo *ScopeName; + SourceLocation ScopeLoc; + IdentifierInfo *ParmName; + SourceLocation ParmLoc; + ActionBase::ExprTy **Args; + unsigned NumArgs; + AttributeList *Next; + bool DeclspecAttribute, CXX0XAttribute; + mutable bool Invalid; /// True if already diagnosed as invalid. + AttributeList(const AttributeList &); // DO NOT IMPLEMENT + void operator=(const AttributeList &); // DO NOT IMPLEMENT +public: + AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + IdentifierInfo *ParmName, SourceLocation ParmLoc, + ActionBase::ExprTy **args, unsigned numargs, + AttributeList *Next, bool declspec = false, bool cxx0x = false); + ~AttributeList(); + + enum Kind { // Please keep this list alphabetized. + AT_IBAction, // Clang-specific. + AT_IBOutlet, // Clang-specific. + AT_IBOutletCollection, // Clang-specific. + AT_address_space, + AT_alias, + AT_aligned, + AT_always_inline, + AT_analyzer_noreturn, + AT_annotate, + AT_base_check, + AT_blocks, + AT_carries_dependency, + AT_cdecl, + AT_cleanup, + AT_const, + AT_constructor, + AT_deprecated, + AT_destructor, + AT_dllexport, + AT_dllimport, + AT_ext_vector_type, + AT_fastcall, + AT_final, + AT_format, + AT_format_arg, + AT_gnu_inline, + AT_hiding, + AT_malloc, + AT_mode, + AT_nodebug, + AT_noinline, + AT_no_instrument_function, + AT_nonnull, + AT_noreturn, + AT_nothrow, + AT_nsobject, + AT_objc_exception, + AT_override, + AT_cf_returns_not_retained, // Clang-specific. + AT_cf_returns_retained, // Clang-specific. + AT_ns_returns_not_retained, // Clang-specific. + AT_ns_returns_retained, // Clang-specific. + AT_objc_gc, + AT_overloadable, // Clang-specific. + AT_packed, + AT_pure, + AT_regparm, + AT_section, + AT_sentinel, + AT_stdcall, + AT_thiscall, + AT_transparent_union, + AT_unavailable, + AT_unused, + AT_used, + AT_vector_size, + AT_visibility, + AT_warn_unused_result, + AT_weak, + AT_weakref, + AT_weak_import, + AT_reqd_wg_size, + IgnoredAttribute, + UnknownAttribute + }; + + IdentifierInfo *getName() const { return AttrName; } + SourceLocation getLoc() const { return AttrLoc; } + + bool hasScope() const { return ScopeName; } + IdentifierInfo *getScopeName() const { return ScopeName; } + SourceLocation getScopeLoc() const { return ScopeLoc; } + + IdentifierInfo *getParameterName() const { return ParmName; } + + bool isDeclspecAttribute() const { return DeclspecAttribute; } + bool isCXX0XAttribute() const { return CXX0XAttribute; } + + bool isInvalid() const { return Invalid; } + void setInvalid(bool b = true) const { Invalid = b; } + + Kind getKind() const { return getKind(getName()); } + static Kind getKind(const IdentifierInfo *Name); + + AttributeList *getNext() const { return Next; } + void setNext(AttributeList *N) { Next = N; } + + /// getNumArgs - Return the number of actual arguments to this attribute. + unsigned getNumArgs() const { return NumArgs; } + + /// getArg - Return the specified argument. + ActionBase::ExprTy *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return Args[Arg]; + } + + class arg_iterator { + ActionBase::ExprTy** X; + unsigned Idx; + public: + arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {} + + arg_iterator& operator++() { + ++Idx; + return *this; + } + + bool operator==(const arg_iterator& I) const { + assert (X == I.X && + "compared arg_iterators are for different argument lists"); + return Idx == I.Idx; + } + + bool operator!=(const arg_iterator& I) const { + return !operator==(I); + } + + ActionBase::ExprTy* operator*() const { + return X[Idx]; + } + + unsigned getArgNum() const { + return Idx+1; + } + }; + + arg_iterator arg_begin() const { + return arg_iterator(Args, 0); + } + + arg_iterator arg_end() const { + return arg_iterator(Args, NumArgs); + } +}; + +/// addAttributeLists - Add two AttributeLists together +/// The right-hand list is appended to the left-hand list, if any +/// A pointer to the joined list is returned. +/// Note: the lists are not left unmodified. +inline AttributeList* addAttributeLists (AttributeList *Left, + AttributeList *Right) { + if (!Left) + return Right; + + AttributeList *next = Left, *prev; + do { + prev = next; + next = next->getNext(); + } while (next); + prev->setNext(Right); + return Left; +} + +/// CXX0XAttributeList - A wrapper around a C++0x attribute list. +/// Stores, in addition to the list proper, whether or not an actual list was +/// (as opposed to an empty list, which may be ill-formed in some places) and +/// the source range of the list. +struct CXX0XAttributeList { + AttributeList *AttrList; + SourceRange Range; + bool HasAttr; + CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) + : AttrList(attrList), Range(range), HasAttr (hasAttr) { + } + CXX0XAttributeList () + : AttrList(0), Range(), HasAttr(false) { + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Parse/DeclSpec.h new file mode 100644 index 0000000..9c19a67 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/DeclSpec.h @@ -0,0 +1,1323 @@ +//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- 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 interfaces used for Declaration Specifiers and Declarators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_DECLSPEC_H +#define LLVM_CLANG_PARSE_DECLSPEC_H + +#include "clang/Parse/AttributeList.h" +#include "clang/Lex/Token.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class LangOptions; + class Diagnostic; + class IdentifierInfo; + class Preprocessor; + class Declarator; + struct TemplateIdAnnotation; + +/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope +/// specifier. These can be in 3 states: +/// 1) Not present, identified by isEmpty() +/// 2) Present, identified by isNotEmpty() +/// 2.a) Valid, idenified by isValid() +/// 2.b) Invalid, identified by isInvalid(). +/// +/// isSet() is deprecated because it mostly corresponded to "valid" but was +/// often used as if it meant "present". +/// +/// The actual scope is described by getScopeRep(). +class CXXScopeSpec { + SourceRange Range; + void *ScopeRep; + +public: + CXXScopeSpec() : Range(), ScopeRep() { } + + const SourceRange &getRange() const { return Range; } + void setRange(const SourceRange &R) { Range = R; } + void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } + void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + + ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } + void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } + + /// No scope specifier. + bool isEmpty() const { return !Range.isValid(); } + /// A scope specifier is present, but may be valid or invalid. + bool isNotEmpty() const { return !isEmpty(); } + + /// An error occured during parsing of the scope specifier. + bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + /// A scope specifier is present, and it refers to a real scope. + bool isValid() const { return isNotEmpty() && ScopeRep != 0; } + + /// Deprecated. Some call sites intend isNotEmpty() while others intend + /// isValid(). + bool isSet() const { return ScopeRep != 0; } + + void clear() { + Range = SourceRange(); + ScopeRep = 0; + } +}; + +/// DeclSpec - This class captures information about "declaration specifiers", +/// which encompasses storage-class-specifiers, type-specifiers, +/// type-qualifiers, and function-specifiers. +class DeclSpec { +public: + // storage-class-specifier + // Note: The order of these enumerators is important for diagnostics. + enum SCS { + SCS_unspecified = 0, + SCS_typedef, + SCS_extern, + SCS_static, + SCS_auto, + SCS_register, + SCS_private_extern, + SCS_mutable + }; + + // Import type specifier width enumeration and constants. + typedef TypeSpecifierWidth TSW; + static const TSW TSW_unspecified = clang::TSW_unspecified; + static const TSW TSW_short = clang::TSW_short; + static const TSW TSW_long = clang::TSW_long; + static const TSW TSW_longlong = clang::TSW_longlong; + + enum TSC { + TSC_unspecified, + TSC_imaginary, + TSC_complex + }; + + // Import type specifier sign enumeration and constants. + typedef TypeSpecifierSign TSS; + static const TSS TSS_unspecified = clang::TSS_unspecified; + static const TSS TSS_signed = clang::TSS_signed; + static const TSS TSS_unsigned = clang::TSS_unsigned; + + // Import type specifier type enumeration and constants. + typedef TypeSpecifierType TST; + static const TST TST_unspecified = clang::TST_unspecified; + static const TST TST_void = clang::TST_void; + static const TST TST_char = clang::TST_char; + static const TST TST_wchar = clang::TST_wchar; + 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_float = clang::TST_float; + static const TST TST_double = clang::TST_double; + static const TST TST_bool = clang::TST_bool; + static const TST TST_decimal32 = clang::TST_decimal32; + static const TST TST_decimal64 = clang::TST_decimal64; + static const TST TST_decimal128 = clang::TST_decimal128; + static const TST TST_enum = clang::TST_enum; + static const TST TST_union = clang::TST_union; + static const TST TST_struct = clang::TST_struct; + static const TST TST_class = clang::TST_class; + static const TST TST_typename = clang::TST_typename; + static const TST TST_typeofType = clang::TST_typeofType; + static const TST TST_typeofExpr = clang::TST_typeofExpr; + static const TST TST_decltype = clang::TST_decltype; + static const TST TST_auto = clang::TST_auto; + static const TST TST_error = clang::TST_error; + + // type-qualifiers + enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ. + TQ_unspecified = 0, + TQ_const = 1, + TQ_restrict = 2, + TQ_volatile = 4 + }; + + /// ParsedSpecifiers - Flags to query which specifiers were applied. This is + /// returned by getParsedSpecifiers. + enum ParsedSpecifiers { + PQ_None = 0, + PQ_StorageClassSpecifier = 1, + PQ_TypeSpecifier = 2, + PQ_TypeQualifier = 4, + PQ_FunctionSpecifier = 8 + }; + +private: + + // storage-class-specifier + /*SCS*/unsigned StorageClassSpec : 3; + bool SCS_thread_specified : 1; + + // type-specifier + /*TSW*/unsigned TypeSpecWidth : 2; + /*TSC*/unsigned TypeSpecComplex : 2; + /*TSS*/unsigned TypeSpecSign : 2; + /*TST*/unsigned TypeSpecType : 5; + bool TypeAltiVecVector : 1; + bool TypeAltiVecPixel : 1; + bool TypeSpecOwned : 1; + + // type-qualifiers + unsigned TypeQualifiers : 3; // Bitwise OR of TQ. + + // function-specifier + bool FS_inline_specified : 1; + bool FS_virtual_specified : 1; + bool FS_explicit_specified : 1; + + // friend-specifier + bool Friend_specified : 1; + + // constexpr-specifier + bool Constexpr_specified : 1; + + /*SCS*/unsigned StorageClassSpecAsWritten : 3; + + /// TypeRep - This contains action-specific information about a specific TST. + /// For example, for a typedef or struct, it might contain the declaration for + /// these. + void *TypeRep; + + // attributes. + AttributeList *AttrList; + + // Scope specifier for the type spec, if applicable. + CXXScopeSpec TypeScope; + + // List of protocol qualifiers for objective-c classes. Used for + // protocol-qualified interfaces "NString<foo>" and protocol-qualified id + // "id<foo>". + const ActionBase::DeclPtrTy *ProtocolQualifiers; + unsigned NumProtocolQualifiers; + SourceLocation ProtocolLAngleLoc; + SourceLocation *ProtocolLocs; + + // SourceLocation info. These are null if the item wasn't specified or if + // the setting was synthesized. + SourceRange Range; + + SourceLocation StorageClassSpecLoc, SCS_threadLoc; + SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; + SourceRange TypeofParensRange; + SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; + SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; + SourceLocation FriendLoc, ConstexprLoc; + + WrittenBuiltinSpecs writtenBS; + void SaveWrittenBuiltinSpecs(); + void SaveStorageSpecifierAsWritten() { + StorageClassSpecAsWritten = StorageClassSpec; + } + + DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT + void operator=(const DeclSpec&); // DO NOT IMPLEMENT +public: + + DeclSpec() + : StorageClassSpec(SCS_unspecified), + SCS_thread_specified(false), + TypeSpecWidth(TSW_unspecified), + TypeSpecComplex(TSC_unspecified), + TypeSpecSign(TSS_unspecified), + TypeSpecType(TST_unspecified), + TypeAltiVecVector(false), + TypeAltiVecPixel(false), + TypeSpecOwned(false), + TypeQualifiers(TSS_unspecified), + FS_inline_specified(false), + FS_virtual_specified(false), + FS_explicit_specified(false), + Friend_specified(false), + Constexpr_specified(false), + StorageClassSpecAsWritten(SCS_unspecified), + TypeRep(0), + AttrList(0), + ProtocolQualifiers(0), + NumProtocolQualifiers(0), + ProtocolLocs(0), + writtenBS() { + } + ~DeclSpec() { + delete AttrList; + delete [] ProtocolQualifiers; + delete [] ProtocolLocs; + } + // storage-class-specifier + SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; } + bool isThreadSpecified() const { return SCS_thread_specified; } + + SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } + SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; } + + void ClearStorageClassSpecs() { + StorageClassSpec = DeclSpec::SCS_unspecified; + SCS_thread_specified = false; + StorageClassSpecLoc = SourceLocation(); + SCS_threadLoc = SourceLocation(); + } + + // type-specifier + TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; } + TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } + TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } + TST getTypeSpecType() const { return (TST)TypeSpecType; } + bool isTypeAltiVecVector() const { return TypeAltiVecVector; } + bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } + bool isTypeSpecOwned() const { return TypeSpecOwned; } + void *getTypeRep() const { return TypeRep; } + CXXScopeSpec &getTypeSpecScope() { return TypeScope; } + const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; } + + const SourceRange &getSourceRange() const { return Range; } + SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } + SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } + SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } + SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } + SourceLocation getAltiVecLoc() const { return AltiVecLoc; } + + SourceRange getTypeofParensRange() const { return TypeofParensRange; } + void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } + + /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool" + /// or "union". + static const char *getSpecifierName(DeclSpec::TST T); + static const char *getSpecifierName(DeclSpec::TQ Q); + static const char *getSpecifierName(DeclSpec::TSS S); + static const char *getSpecifierName(DeclSpec::TSC C); + static const char *getSpecifierName(DeclSpec::TSW W); + static const char *getSpecifierName(DeclSpec::SCS S); + + // type-qualifiers + + /// getTypeQualifiers - Return a set of TQs. + unsigned getTypeQualifiers() const { return TypeQualifiers; } + SourceLocation getConstSpecLoc() const { return TQ_constLoc; } + SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } + SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } + + // function-specifier + bool isInlineSpecified() const { return FS_inline_specified; } + SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; } + + bool isVirtualSpecified() const { return FS_virtual_specified; } + SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; } + + bool isExplicitSpecified() const { return FS_explicit_specified; } + SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; } + + void ClearFunctionSpecs() { + FS_inline_specified = false; + FS_inlineLoc = SourceLocation(); + FS_virtual_specified = false; + FS_virtualLoc = SourceLocation(); + FS_explicit_specified = false; + FS_explicitLoc = SourceLocation(); + } + + /// hasTypeSpecifier - Return true if any type-specifier has been found. + bool hasTypeSpecifier() const { + return getTypeSpecType() != DeclSpec::TST_unspecified || + getTypeSpecWidth() != DeclSpec::TSW_unspecified || + getTypeSpecComplex() != DeclSpec::TSC_unspecified || + getTypeSpecSign() != DeclSpec::TSS_unspecified; + } + + /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this + /// DeclSpec includes. + /// + unsigned getParsedSpecifiers() const; + + SCS getStorageClassSpecAsWritten() const { + return (SCS)StorageClassSpecAsWritten; + } + + /// isEmpty - Return true if this declaration specifier is completely empty: + /// no tokens were parsed in the production of it. + bool isEmpty() const { + return getParsedSpecifiers() == DeclSpec::PQ_None; + } + + void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } + void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } + + /// These methods set the specified attribute of the DeclSpec and + /// return false if there was no error. If an error occurs (for + /// example, if we tried to set "auto" on a spec with "extern" + /// already set), they return true and set PrevSpec and DiagID + /// such that + /// Diag(Loc, DiagID) << PrevSpec; + /// will yield a useful result. + /// + /// TODO: use a more general approach that still allows these + /// diagnostics to be ignored when desired. + bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, void *Rep = 0, bool Owned = false); + bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); + bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); + bool SetTypeSpecError(); + void UpdateTypeRep(void *Rep) { TypeRep = Rep; } + + bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, const LangOptions &Lang); + + bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + + bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + + bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + + bool isFriendSpecified() const { return Friend_specified; } + SourceLocation getFriendSpecLoc() const { return FriendLoc; } + + bool isConstexprSpecified() const { return Constexpr_specified; } + SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + + /// AddAttributes - contatenates two attribute lists. + /// The GCC attribute syntax allows for the following: + /// + /// short __attribute__(( unused, deprecated )) + /// int __attribute__(( may_alias, aligned(16) )) var; + /// + /// This declares 4 attributes using 2 lists. The following syntax is + /// also allowed and equivalent to the previous declaration. + /// + /// short __attribute__((unused)) __attribute__((deprecated)) + /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; + /// + void AddAttributes(AttributeList *alist) { + AttrList = addAttributeLists(AttrList, alist); + } + void SetAttributes(AttributeList *AL) { AttrList = AL; } + const AttributeList *getAttributes() const { return AttrList; } + AttributeList *getAttributes() { return AttrList; } + + /// TakeAttributes - Return the current attribute list and remove them from + /// the DeclSpec so that it doesn't own them. + AttributeList *TakeAttributes() { + AttributeList *AL = AttrList; + AttrList = 0; + return AL; + } + + typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy; + ProtocolQualifierListTy getProtocolQualifiers() const { + return ProtocolQualifiers; + } + SourceLocation *getProtocolLocs() const { return ProtocolLocs; } + unsigned getNumProtocolQualifiers() const { + return NumProtocolQualifiers; + } + SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; } + void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP, + SourceLocation *ProtoLocs, + SourceLocation LAngleLoc); + + /// Finish - This does final analysis of the declspec, issuing diagnostics for + /// things like "_Imaginary" (lacking an FP type). After calling this method, + /// DeclSpec is guaranteed self-consistent, even if an error occurred. + void Finish(Diagnostic &D, Preprocessor &PP); + + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { + return writtenBS; + } + + /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone, + /// without a Declarator. Only tag declspecs can stand alone. + bool isMissingDeclaratorOk(); +}; + +/// ObjCDeclSpec - This class captures information about +/// "declaration specifiers" specific to objective-c +class ObjCDeclSpec { +public: + /// ObjCDeclQualifier - Qualifier used on types in method declarations + enum ObjCDeclQualifier { + DQ_None = 0x0, + DQ_In = 0x1, + DQ_Inout = 0x2, + DQ_Out = 0x4, + DQ_Bycopy = 0x8, + DQ_Byref = 0x10, + DQ_Oneway = 0x20 + }; + + /// PropertyAttributeKind - list of property attributes. + enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, + DQ_PR_readonly = 0x01, + DQ_PR_getter = 0x02, + DQ_PR_assign = 0x04, + DQ_PR_readwrite = 0x08, + DQ_PR_retain = 0x10, + DQ_PR_copy = 0x20, + DQ_PR_nonatomic = 0x40, + DQ_PR_setter = 0x80 + }; + + + ObjCDeclSpec() + : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), + GetterName(0), SetterName(0) { } + ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } + void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { + objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); + } + + ObjCPropertyAttributeKind getPropertyAttributes() const { + return ObjCPropertyAttributeKind(PropertyAttributes); + } + void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { + PropertyAttributes = + (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal); + } + + const IdentifierInfo *getGetterName() const { return GetterName; } + IdentifierInfo *getGetterName() { return GetterName; } + void setGetterName(IdentifierInfo *name) { GetterName = name; } + + const IdentifierInfo *getSetterName() const { return SetterName; } + IdentifierInfo *getSetterName() { return SetterName; } + void setSetterName(IdentifierInfo *name) { SetterName = name; } +private: + // FIXME: These two are unrelated and mutially exclusive. So perhaps + // we can put them in a union to reflect their mutual exclusiveness + // (space saving is negligible). + ObjCDeclQualifier objcDeclQualifier : 6; + + // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind + unsigned PropertyAttributes : 8; + IdentifierInfo *GetterName; // getter name of NULL if no getter + IdentifierInfo *SetterName; // setter name of NULL if no setter +}; + +/// \brief Represents a C++ unqualified-id that has been parsed. +class UnqualifiedId { +private: + const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT + +public: + /// \brief Describes the kind of unqualified-id parsed. + enum IdKind { + /// \brief An identifier. + IK_Identifier, + /// \brief An overloaded operator name, e.g., operator+. + IK_OperatorFunctionId, + /// \brief A conversion function name, e.g., operator int. + IK_ConversionFunctionId, + /// \brief A user-defined literal name, e.g., operator "" _i. + IK_LiteralOperatorId, + /// \brief A constructor name. + IK_ConstructorName, + /// \brief A constructor named via a template-id. + IK_ConstructorTemplateId, + /// \brief A destructor name. + IK_DestructorName, + /// \brief A template-id, e.g., f<int>. + IK_TemplateId + } Kind; + + /// \brief Anonymous union that holds extra data associated with the + /// parsed unqualified-id. + union { + /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind + /// == IK_UserLiteralId, the identifier suffix. + IdentifierInfo *Identifier; + + /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator + /// that we parsed. + struct { + /// \brief The kind of overloaded operator. + OverloadedOperatorKind Operator; + + /// \brief The source locations of the individual tokens that name + /// the operator, e.g., the "new", "[", and "]" tokens in + /// operator new []. + /// + /// Different operators have different numbers of tokens in their name, + /// up to three. Any remaining source locations in this array will be + /// set to an invalid value for operators with fewer than three tokens. + unsigned SymbolLocations[3]; + } OperatorFunctionId; + + /// \brief When Kind == IK_ConversionFunctionId, the type that the + /// conversion function names. + ActionBase::TypeTy *ConversionFunctionId; + + /// \brief When Kind == IK_ConstructorName, the class-name of the type + /// whose constructor is being referenced. + ActionBase::TypeTy *ConstructorName; + + /// \brief When Kind == IK_DestructorName, the type referred to by the + /// class-name. + ActionBase::TypeTy *DestructorName; + + /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId, + /// the template-id annotation that contains the template name and + /// template arguments. + TemplateIdAnnotation *TemplateId; + }; + + /// \brief The location of the first token that describes this unqualified-id, + /// which will be the location of the identifier, "operator" keyword, + /// tilde (for a destructor), or the template name of a template-id. + SourceLocation StartLocation; + + /// \brief The location of the last token that describes this unqualified-id. + SourceLocation EndLocation; + + UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { } + + /// \brief Do not use this copy constructor. It is temporary, and only + /// exists because we are holding FieldDeclarators in a SmallVector when we + /// don't actually need them. + /// + /// FIXME: Kill this copy constructor. + UnqualifiedId(const UnqualifiedId &Other) + : Kind(IK_Identifier), Identifier(Other.Identifier), + StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) { + assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers"); + } + + /// \brief Destroy this unqualified-id. + ~UnqualifiedId() { clear(); } + + /// \brief Clear out this unqualified-id, setting it to default (invalid) + /// state. + void clear(); + + /// \brief Determine whether this unqualified-id refers to a valid name. + bool isValid() const { return StartLocation.isValid(); } + + /// \brief Determine whether this unqualified-id refers to an invalid name. + bool isInvalid() const { return !isValid(); } + + /// \brief Determine what kind of name we have. + IdKind getKind() const { return Kind; } + + /// \brief Specify that this unqualified-id was parsed as an identifier. + /// + /// \param Id the parsed identifier. + /// \param IdLoc the location of the parsed identifier. + void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) { + Kind = IK_Identifier; + Identifier = const_cast<IdentifierInfo *>(Id); + StartLocation = EndLocation = IdLoc; + } + + /// \brief Specify that this unqualified-id was parsed as an + /// operator-function-id. + /// + /// \param OperatorLoc the location of the 'operator' keyword. + /// + /// \param Op the overloaded operator. + /// + /// \param SymbolLocations the locations of the individual operator symbols + /// in the operator. + void setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]); + + /// \brief Specify that this unqualified-id was parsed as a + /// conversion-function-id. + /// + /// \param OperatorLoc the location of the 'operator' keyword. + /// + /// \param Ty the type to which this conversion function is converting. + /// + /// \param EndLoc the location of the last token that makes up the type name. + void setConversionFunctionId(SourceLocation OperatorLoc, + ActionBase::TypeTy *Ty, + SourceLocation EndLoc) { + Kind = IK_ConversionFunctionId; + StartLocation = OperatorLoc; + EndLocation = EndLoc; + ConversionFunctionId = Ty; + } + + /// \brief Specific that this unqualified-id was parsed as a + /// literal-operator-id. + /// + /// \param Id the parsed identifier. + /// + /// \param OpLoc the location of the 'operator' keyword. + /// + /// \param IdLoc the location of the identifier. + void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc, + SourceLocation IdLoc) { + Kind = IK_LiteralOperatorId; + Identifier = const_cast<IdentifierInfo *>(Id); + StartLocation = OpLoc; + EndLocation = IdLoc; + } + + /// \brief Specify that this unqualified-id was parsed as a constructor name. + /// + /// \param ClassType the class type referred to by the constructor name. + /// + /// \param ClassNameLoc the location of the class name. + /// + /// \param EndLoc the location of the last token that makes up the type name. + void setConstructorName(ActionBase::TypeTy *ClassType, + SourceLocation ClassNameLoc, + SourceLocation EndLoc) { + Kind = IK_ConstructorName; + StartLocation = ClassNameLoc; + EndLocation = EndLoc; + ConstructorName = ClassType; + } + + /// \brief Specify that this unqualified-id was parsed as a + /// template-id that names a constructor. + /// + /// \param TemplateId the template-id annotation that describes the parsed + /// template-id. This UnqualifiedId instance will take ownership of the + /// \p TemplateId and will free it on destruction. + void setConstructorTemplateId(TemplateIdAnnotation *TemplateId); + + /// \brief Specify that this unqualified-id was parsed as a destructor name. + /// + /// \param TildeLoc the location of the '~' that introduces the destructor + /// name. + /// + /// \param ClassType the name of the class referred to by the destructor name. + void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType, + SourceLocation EndLoc) { + Kind = IK_DestructorName; + StartLocation = TildeLoc; + EndLocation = EndLoc; + DestructorName = ClassType; + } + + /// \brief Specify that this unqualified-id was parsed as a template-id. + /// + /// \param TemplateId the template-id annotation that describes the parsed + /// template-id. This UnqualifiedId instance will take ownership of the + /// \p TemplateId and will free it on destruction. + void setTemplateId(TemplateIdAnnotation *TemplateId); + + /// \brief Return the source range that covers this unqualified-id. + SourceRange getSourceRange() const { + return SourceRange(StartLocation, EndLocation); + } +}; + +/// CachedTokens - A set of tokens that has been cached for later +/// parsing. +typedef llvm::SmallVector<Token, 4> CachedTokens; + +/// DeclaratorChunk - One instance of this struct is used for each type in a +/// declarator that is parsed. +/// +/// This is intended to be a small value object. +struct DeclaratorChunk { + enum { + Pointer, Reference, Array, Function, BlockPointer, MemberPointer + } Kind; + + /// Loc - The place where this type was defined. + SourceLocation Loc; + /// EndLoc - If valid, the place where this chunck ends. + SourceLocation EndLoc; + + struct PointerTypeInfo { + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct ReferenceTypeInfo { + /// The type qualifier: restrict. [GNU] C++ extension + bool HasRestrict : 1; + /// True if this is an lvalue reference, false if it's an rvalue reference. + bool LValueRef : 1; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct ArrayTypeInfo { + /// The type qualifiers for the array: const/volatile/restrict. + unsigned TypeQuals : 3; + + /// True if this dimension included the 'static' keyword. + bool hasStatic : 1; + + /// True if this dimension was [*]. In this case, NumElts is null. + bool isStar : 1; + + /// This is the size of the array, or null if [] or [*] was specified. + /// Since the parser is multi-purpose, and we don't want to impose a root + /// expression class on all clients, NumElts is untyped. + ActionBase::ExprTy *NumElts; + void destroy() {} + }; + + /// ParamInfo - An array of paraminfo objects is allocated whenever a function + /// declarator is parsed. There are two interesting styles of arguments here: + /// K&R-style identifier lists and parameter type lists. K&R-style identifier + /// lists will have information about the identifier, but no type information. + /// Parameter type lists will have type info (if the actions module provides + /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'. + struct ParamInfo { + IdentifierInfo *Ident; + SourceLocation IdentLoc; + ActionBase::DeclPtrTy Param; + + /// DefaultArgTokens - When the parameter's default argument + /// cannot be parsed immediately (because it occurs within the + /// declaration of a member function), it will be stored here as a + /// sequence of tokens to be parsed once the class definition is + /// complete. Non-NULL indicates that there is a default argument. + CachedTokens *DefaultArgTokens; + + ParamInfo() {} + ParamInfo(IdentifierInfo *ident, SourceLocation iloc, + ActionBase::DeclPtrTy param, + CachedTokens *DefArgTokens = 0) + : Ident(ident), IdentLoc(iloc), Param(param), + DefaultArgTokens(DefArgTokens) {} + }; + + struct TypeAndRange { + ActionBase::TypeTy *Ty; + SourceRange Range; + }; + + struct FunctionTypeInfo { + /// hasPrototype - This is true if the function had at least one typed + /// argument. If the function is () or (a,b,c), then it has no prototype, + /// and is treated as a K&R-style function. + bool hasPrototype : 1; + + /// isVariadic - If this function has a prototype, and if that + /// proto ends with ',...)', this is true. When true, EllipsisLoc + /// contains the location of the ellipsis. + bool isVariadic : 1; + + /// The type qualifiers: const/volatile/restrict. + /// The qualifier bitmask values are the same as in QualType. + unsigned TypeQuals : 3; + + /// hasExceptionSpec - True if the function has an exception specification. + bool hasExceptionSpec : 1; + + /// hasAnyExceptionSpec - True if the function has a throw(...) specifier. + bool hasAnyExceptionSpec : 1; + + /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. + bool DeleteArgInfo : 1; + + /// When isVariadic is true, the location of the ellipsis in the source. + unsigned EllipsisLoc; + + /// NumArgs - This is the number of formal arguments provided for the + /// declarator. + unsigned NumArgs; + + /// NumExceptions - This is the number of types in the exception-decl, if + /// the function has one. + unsigned NumExceptions; + + /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + /// keyword introducing the spec. + unsigned ThrowLoc; + + /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that + /// describe the arguments for this function declarator. This is null if + /// there are no arguments specified. + ParamInfo *ArgInfo; + + /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange + /// objects that contain the types in the function's exception + /// specification and their locations. + TypeAndRange *Exceptions; + + /// freeArgs - reset the argument list to having zero arguments. This is + /// used in various places for error recovery. + void freeArgs() { + if (DeleteArgInfo) { + delete[] ArgInfo; + DeleteArgInfo = false; + } + NumArgs = 0; + } + + void destroy() { + if (DeleteArgInfo) + delete[] ArgInfo; + delete[] Exceptions; + } + + SourceLocation getEllipsisLoc() const { + return SourceLocation::getFromRawEncoding(EllipsisLoc); + } + SourceLocation getThrowLoc() const { + return SourceLocation::getFromRawEncoding(ThrowLoc); + } + }; + + struct BlockPointerTypeInfo { + /// For now, sema will catch these as invalid. + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct MemberPointerTypeInfo { + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + // CXXScopeSpec has a constructor, so it can't be a direct member. + // So we need some pointer-aligned storage and a bit of trickery. + union { + void *Aligner; + char Mem[sizeof(CXXScopeSpec)]; + } ScopeMem; + CXXScopeSpec &Scope() { + return *reinterpret_cast<CXXScopeSpec*>(ScopeMem.Mem); + } + const CXXScopeSpec &Scope() const { + return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem); + } + void destroy() { + delete AttrList; + Scope().~CXXScopeSpec(); + } + }; + + union { + PointerTypeInfo Ptr; + ReferenceTypeInfo Ref; + ArrayTypeInfo Arr; + FunctionTypeInfo Fun; + BlockPointerTypeInfo Cls; + MemberPointerTypeInfo Mem; + }; + + void destroy() { + switch (Kind) { + default: assert(0 && "Unknown decl type!"); + case DeclaratorChunk::Function: return Fun.destroy(); + case DeclaratorChunk::Pointer: return Ptr.destroy(); + case DeclaratorChunk::BlockPointer: return Cls.destroy(); + case DeclaratorChunk::Reference: return Ref.destroy(); + case DeclaratorChunk::Array: return Arr.destroy(); + case DeclaratorChunk::MemberPointer: return Mem.destroy(); + } + } + + /// getAttrs - If there are attributes applied to this declaratorchunk, return + /// them. + const AttributeList *getAttrs() const { + switch (Kind) { + default: assert(0 && "Unknown declarator kind!"); + case Pointer: return Ptr.AttrList; + case Reference: return Ref.AttrList; + case MemberPointer: return Mem.AttrList; + case Array: return 0; + case Function: return 0; + case BlockPointer: return Cls.AttrList; + } + } + + + /// getPointer - Return a DeclaratorChunk for a pointer. + /// + static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = Pointer; + I.Loc = Loc; + I.Ptr.TypeQuals = TypeQuals; + I.Ptr.AttrList = AL; + return I; + } + + /// getReference - Return a DeclaratorChunk for a reference. + /// + static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL, bool lvalue) { + DeclaratorChunk I; + I.Kind = Reference; + I.Loc = Loc; + I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; + I.Ref.LValueRef = lvalue; + I.Ref.AttrList = AL; + return I; + } + + /// getArray - Return a DeclaratorChunk for an array. + /// + static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, + bool isStar, void *NumElts, + SourceLocation LBLoc, SourceLocation RBLoc) { + DeclaratorChunk I; + I.Kind = Array; + I.Loc = LBLoc; + I.EndLoc = RBLoc; + I.Arr.TypeQuals = TypeQuals; + I.Arr.hasStatic = isStatic; + I.Arr.isStar = isStar; + I.Arr.NumElts = NumElts; + return I; + } + + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. + /// "TheDeclarator" is the declarator that this will be added to. + static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, + SourceLocation EllipsisLoc, + ParamInfo *ArgInfo, unsigned NumArgs, + unsigned TypeQuals, bool hasExceptionSpec, + SourceLocation ThrowLoc, + bool hasAnyExceptionSpec, + ActionBase::TypeTy **Exceptions, + SourceRange *ExceptionRanges, + unsigned NumExceptions, + SourceLocation LPLoc, SourceLocation RPLoc, + Declarator &TheDeclarator); + + /// getBlockPointer - Return a DeclaratorChunk for a block. + /// + static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = BlockPointer; + I.Loc = Loc; + I.Cls.TypeQuals = TypeQuals; + I.Cls.AttrList = AL; + return I; + } + + static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, + unsigned TypeQuals, + SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = MemberPointer; + I.Loc = Loc; + I.Mem.TypeQuals = TypeQuals; + I.Mem.AttrList = AL; + new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); + return I; + } +}; + +/// 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. +/// +/// Declarators come in two types: normal declarators and abstract declarators. +/// Abstract declarators are used when parsing types, and don't have an +/// identifier. Normal declarators do have ID's. +/// +/// Instances of this class should be a transient object that lives on the +/// stack, not objects that are allocated in large quantities on the heap. +class Declarator { +public: + enum TheContext { + FileContext, // File scope declaration. + PrototypeContext, // Within a function prototype. + KNRTypeListContext, // K&R type definition list for formals. + TypeNameContext, // Abstract declarator for types. + MemberContext, // Struct/Union field. + BlockContext, // Declaration within a block in a function. + ForContext, // Declaration within first part of a for loop. + ConditionContext, // Condition declaration in a C++ if/switch/while/for. + TemplateParamContext,// Within a template parameter list. + CXXCatchContext, // C++ catch exception-declaration + BlockLiteralContext // Block literal declarator. + }; + +private: + const DeclSpec &DS; + CXXScopeSpec SS; + UnqualifiedId Name; + SourceRange Range; + + /// Context - Where we are parsing this declarator. + /// + TheContext Context; + + /// DeclTypeInfo - This holds each type that the declarator includes as it is + /// parsed. This is pushed from the identifier out, which means that element + /// #0 will be the most closely bound to the identifier, and + /// DeclTypeInfo.back() will be the least closely bound. + llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo; + + /// InvalidType - Set by Sema::GetTypeForDeclarator(). + bool InvalidType : 1; + + /// GroupingParens - Set by Parser::ParseParenDeclarator(). + bool GroupingParens : 1; + + /// AttrList - Attributes. + AttributeList *AttrList; + + /// AsmLabel - The asm label, if specified. + ActionBase::ExprTy *AsmLabel; + + /// InlineParams - This is a local array used for the first function decl + /// chunk to avoid going to the heap for the common case when we have one + /// function chunk in the declarator. + DeclaratorChunk::ParamInfo InlineParams[16]; + bool InlineParamsUsed; + + /// Extension - true if the declaration is preceded by __extension__. + bool Extension : 1; + + friend struct DeclaratorChunk; + +public: + Declarator(const DeclSpec &ds, TheContext C) + : DS(ds), Range(ds.getSourceRange()), Context(C), + InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), + GroupingParens(false), AttrList(0), AsmLabel(0), + InlineParamsUsed(false), Extension(false) { + } + + ~Declarator() { + clear(); + } + + /// getDeclSpec - Return the declaration-specifier that this declarator was + /// declared with. + const DeclSpec &getDeclSpec() const { return DS; } + + /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This + /// should be used with extreme care: declspecs can often be shared between + /// multiple declarators, so mutating the DeclSpec affects all of the + /// Declarators. This should only be done when the declspec is known to not + /// be shared or when in error recovery etc. + DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); } + + /// getCXXScopeSpec - Return the C++ scope specifier (global scope or + /// nested-name-specifier) that is part of the declarator-id. + const CXXScopeSpec &getCXXScopeSpec() const { return SS; } + CXXScopeSpec &getCXXScopeSpec() { return SS; } + + /// \brief Retrieve the name specified by this declarator. + UnqualifiedId &getName() { return Name; } + + TheContext getContext() const { return Context; } + + /// getSourceRange - Get the source range that spans this declarator. + const SourceRange &getSourceRange() const { return Range; } + + void SetSourceRange(SourceRange R) { Range = R; } + /// SetRangeBegin - Set the start of the source range to Loc, unless it's + /// invalid. + void SetRangeBegin(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setBegin(Loc); + } + /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid. + void SetRangeEnd(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setEnd(Loc); + } + /// ExtendWithDeclSpec - Extend the declarator source range to include the + /// given declspec, unless its location is invalid. Adopts the range start if + /// the current range start is invalid. + void ExtendWithDeclSpec(const DeclSpec &DS) { + const SourceRange &SR = DS.getSourceRange(); + if (Range.getBegin().isInvalid()) + Range.setBegin(SR.getBegin()); + if (!SR.getEnd().isInvalid()) + Range.setEnd(SR.getEnd()); + } + + /// clear - Reset the contents of this Declarator. + void clear() { + SS.clear(); + Name.clear(); + Range = DS.getSourceRange(); + + for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) + DeclTypeInfo[i].destroy(); + DeclTypeInfo.clear(); + delete AttrList; + AttrList = 0; + AsmLabel = 0; + InlineParamsUsed = false; + } + + /// mayOmitIdentifier - Return true if the identifier is either optional or + /// not allowed. This is true for typenames, prototypes, and template + /// parameter lists. + bool mayOmitIdentifier() const { + return Context == TypeNameContext || Context == PrototypeContext || + Context == TemplateParamContext || Context == CXXCatchContext || + Context == BlockLiteralContext; + } + + /// mayHaveIdentifier - Return true if the identifier is either optional or + /// required. This is true for normal declarators and prototypes, but not + /// typenames. + bool mayHaveIdentifier() const { + return Context != TypeNameContext && Context != BlockLiteralContext; + } + + /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be + /// followed by a C++ direct initializer, e.g. "int x(1);". + bool mayBeFollowedByCXXDirectInit() const { + return !hasGroupingParens() && + (Context == FileContext || + Context == BlockContext || + Context == ForContext); + } + + /// isPastIdentifier - Return true if we have parsed beyond the point where + /// the + bool isPastIdentifier() const { return Name.isValid(); } + + /// hasName - Whether this declarator has a name, which might be an + /// identifier (accessible via getIdentifier()) or some kind of + /// special C++ name (constructor, destructor, etc.). + bool hasName() const { + return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier; + } + + IdentifierInfo *getIdentifier() const { + if (Name.getKind() == UnqualifiedId::IK_Identifier) + return Name.Identifier; + + return 0; + } + SourceLocation getIdentifierLoc() const { return Name.StartLocation; } + + /// \brief Set the name of this declarator to be the given identifier. + void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) { + Name.setIdentifier(Id, IdLoc); + } + + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to + /// EndLoc, which should be the last token of the chunk. + void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + DeclTypeInfo.push_back(TI); + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// getNumTypeObjects() - Return the number of types applied to this + /// declarator. + unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } + + /// Return the specified TypeInfo from this declarator. TypeInfo #0 is + /// closest to the identifier. + const DeclaratorChunk &getTypeObject(unsigned i) const { + assert(i < DeclTypeInfo.size() && "Invalid type chunk"); + return DeclTypeInfo[i]; + } + DeclaratorChunk &getTypeObject(unsigned i) { + assert(i < DeclTypeInfo.size() && "Invalid type chunk"); + return DeclTypeInfo[i]; + } + + void DropFirstTypeObject() + { + assert(!DeclTypeInfo.empty() && "No type chunks to drop."); + DeclTypeInfo.front().destroy(); + DeclTypeInfo.erase(DeclTypeInfo.begin()); + } + + /// isFunctionDeclarator - Once this declarator is fully parsed and formed, + /// this method returns true if the identifier is a function declarator. + bool isFunctionDeclarator() const { + return !DeclTypeInfo.empty() && + DeclTypeInfo[0].Kind == DeclaratorChunk::Function; + } + + /// AddAttributes - simply adds the attribute list to the Declarator. + /// These examples both add 3 attributes to "var": + /// short int var __attribute__((aligned(16),common,deprecated)); + /// short int x, __attribute__((aligned(16)) var + /// __attribute__((common,deprecated)); + /// + /// Also extends the range of the declarator. + void AddAttributes(AttributeList *alist, SourceLocation LastLoc) { + AttrList = addAttributeLists(AttrList, alist); + + if (!LastLoc.isInvalid()) + SetRangeEnd(LastLoc); + } + + const AttributeList *getAttributes() const { return AttrList; } + AttributeList *getAttributes() { return AttrList; } + + /// hasAttributes - do we contain any attributes? + bool hasAttributes() const { + if (getAttributes() || getDeclSpec().getAttributes()) return true; + for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) + if (getTypeObject(i).getAttrs()) + return true; + return false; + } + + void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; } + ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; } + + void setExtension(bool Val = true) { Extension = Val; } + bool getExtension() const { return Extension; } + + void setInvalidType(bool Val = true) { InvalidType = Val; } + bool isInvalidType() const { + return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; + } + + void setGroupingParens(bool flag) { GroupingParens = flag; } + bool hasGroupingParens() const { return GroupingParens; } +}; + +/// FieldDeclarator - This little struct is used to capture information about +/// structure field declarators, which is basically just a bitfield size. +struct FieldDeclarator { + Declarator D; + ActionBase::ExprTy *BitfieldSize; + explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { + BitfieldSize = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Designator.h b/contrib/llvm/tools/clang/include/clang/Parse/Designator.h new file mode 100644 index 0000000..255af59 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Designator.h @@ -0,0 +1,239 @@ +//===--- Designator.h - Initialization Designator ---------------*- 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 interfaces used to represent Designators in the parser and +// is the input to Actions module. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H +#define LLVM_CLANG_PARSE_DESIGNATOR_H + +#include "clang/Parse/Action.h" + +namespace clang { + +/// Designator - This class is a discriminated union which holds the various +/// different sorts of designators possible. A Designation is an array of +/// these. An example of a designator are things like this: +/// [8] .field [47] // C99 designation: 3 designators +/// [8 ... 47] field: // GNU extensions: 2 designators +/// These occur in initializers, e.g.: +/// int a[10] = {2, 4, [8]=9, 10}; +/// +class Designator { +public: + enum DesignatorKind { + FieldDesignator, ArrayDesignator, ArrayRangeDesignator + }; +private: + DesignatorKind Kind; + + struct FieldDesignatorInfo { + const IdentifierInfo *II; + unsigned DotLoc; + unsigned NameLoc; + }; + struct ArrayDesignatorInfo { + ActionBase::ExprTy *Index; + unsigned LBracketLoc; + mutable unsigned RBracketLoc; + }; + struct ArrayRangeDesignatorInfo { + ActionBase::ExprTy *Start, *End; + unsigned LBracketLoc, EllipsisLoc; + mutable unsigned RBracketLoc; + }; + + union { + FieldDesignatorInfo FieldInfo; + ArrayDesignatorInfo ArrayInfo; + ArrayRangeDesignatorInfo ArrayRangeInfo; + }; + +public: + + DesignatorKind getKind() const { return Kind; } + bool isFieldDesignator() const { return Kind == FieldDesignator; } + bool isArrayDesignator() const { return Kind == ArrayDesignator; } + bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } + + const IdentifierInfo *getField() const { + assert(isFieldDesignator() && "Invalid accessor"); + return FieldInfo.II; + } + + SourceLocation getDotLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc); + } + + SourceLocation getFieldLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc); + } + + ActionBase::ExprTy *getArrayIndex() const { + assert(isArrayDesignator() && "Invalid accessor"); + return ArrayInfo.Index; + } + + ActionBase::ExprTy *getArrayRangeStart() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.Start; + } + ActionBase::ExprTy *getArrayRangeEnd() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.End; + } + + SourceLocation getLBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc); + } + + static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc, + SourceLocation NameLoc) { + Designator D; + D.Kind = FieldDesignator; + D.FieldInfo.II = II; + D.FieldInfo.DotLoc = DotLoc.getRawEncoding(); + D.FieldInfo.NameLoc = NameLoc.getRawEncoding(); + return D; + } + + static Designator getArray(ActionBase::ExprTy *Index, + SourceLocation LBracketLoc) { + Designator D; + D.Kind = ArrayDesignator; + D.ArrayInfo.Index = Index; + D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayInfo.RBracketLoc = 0; + return D; + } + + static Designator getArrayRange(ActionBase::ExprTy *Start, + ActionBase::ExprTy *End, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc) { + Designator D; + D.Kind = ArrayRangeDesignator; + D.ArrayRangeInfo.Start = Start; + D.ArrayRangeInfo.End = End; + D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding(); + D.ArrayRangeInfo.RBracketLoc = 0; + return D; + } + + void setRBracketLoc(SourceLocation RBracketLoc) const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + else + ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + /// ClearExprs - Null out any expression references, which prevents them from + /// being 'delete'd later. + void ClearExprs(Action &Actions) { + switch (Kind) { + case FieldDesignator: return; + case ArrayDesignator: + ArrayInfo.Index = 0; + return; + case ArrayRangeDesignator: + ArrayRangeInfo.Start = 0; + ArrayRangeInfo.End = 0; + return; + } + } + + /// FreeExprs - Release any unclaimed memory for the expressions in this + /// designator. + void FreeExprs(Action &Actions) { + switch (Kind) { + case FieldDesignator: return; // nothing to free. + case ArrayDesignator: + Actions.DeleteExpr(getArrayIndex()); + return; + case ArrayRangeDesignator: + Actions.DeleteExpr(getArrayRangeStart()); + Actions.DeleteExpr(getArrayRangeEnd()); + return; + } + } +}; + + +/// Designation - Represent a full designation, which is a sequence of +/// designators. This class is mostly a helper for InitListDesignations. +class Designation { + /// InitIndex - The index of the initializer expression this is for. For + /// example, if the initializer were "{ A, .foo=B, C }" a Designation would + /// exist with InitIndex=1, because element #1 has a designation. + unsigned InitIndex; + + /// Designators - The actual designators for this initializer. + llvm::SmallVector<Designator, 2> Designators; + + Designation(unsigned Idx) : InitIndex(Idx) {} +public: + Designation() : InitIndex(4000) {} + + /// AddDesignator - Add a designator to the end of this list. + void AddDesignator(Designator D) { + Designators.push_back(D); + } + + bool empty() const { return Designators.empty(); } + + unsigned getNumDesignators() const { return Designators.size(); } + const Designator &getDesignator(unsigned Idx) const { + assert(Idx < Designators.size()); + return Designators[Idx]; + } + + /// ClearExprs - Null out any expression references, which prevents them from + /// being 'delete'd later. + void ClearExprs(Action &Actions) { + for (unsigned i = 0, e = Designators.size(); i != e; ++i) + Designators[i].ClearExprs(Actions); + } + + /// FreeExprs - Release any unclaimed memory for the expressions in this + /// designation. + void FreeExprs(Action &Actions) { + for (unsigned i = 0, e = Designators.size(); i != e; ++i) + Designators[i].FreeExprs(Actions); + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Ownership.h b/contrib/llvm/tools/clang/include/clang/Parse/Ownership.h new file mode 100644 index 0000000..e9a20b7 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Ownership.h @@ -0,0 +1,845 @@ +//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains classes for managing ownership of Stmt and Expr nodes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H +#define LLVM_CLANG_PARSE_OWNERSHIP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" + +//===----------------------------------------------------------------------===// +// OpaquePtr +//===----------------------------------------------------------------------===// + +namespace clang { + class ActionBase; + + /// OpaquePtr - This is a very simple POD type that wraps a pointer that the + /// Parser doesn't know about but that Sema or another client does. The UID + /// template argument is used to make sure that "Decl" pointers are not + /// compatible with "Type" pointers for example. + template<int UID> + class OpaquePtr { + void *Ptr; + public: + OpaquePtr() : Ptr(0) {} + + template <typename T> + T* getAs() const { + return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr); + } + + template <typename T> + T getAsVal() const { + return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr); + } + + void *get() const { return Ptr; } + + template<typename T> + static OpaquePtr make(T P) { + OpaquePtr R; R.set(P); return R; + } + + template<typename T> + void set(T P) { + Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P); + } + + operator bool() const { return Ptr != 0; } + }; +} + +namespace llvm { + template <int UID> + class PointerLikeTypeTraits<clang::OpaquePtr<UID> > { + public: + static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) { + // FIXME: Doesn't work? return P.getAs< void >(); + return P.get(); + } + static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) { + return clang::OpaquePtr<UID>::make(P); + } + enum { NumLowBitsAvailable = 3 }; + }; +} + + + +// -------------------------- About Move Emulation -------------------------- // +// The smart pointer classes in this file attempt to emulate move semantics +// as they appear in C++0x with rvalue references. Since C++03 doesn't have +// rvalue references, some tricks are needed to get similar results. +// Move semantics in C++0x have the following properties: +// 1) "Moving" means transferring the value of an object to another object, +// similar to copying, but without caring what happens to the old object. +// In particular, this means that the new object can steal the old object's +// resources instead of creating a copy. +// 2) Since moving can modify the source object, it must either be explicitly +// requested by the user, or the modifications must be unnoticeable. +// 3) As such, C++0x moving is only allowed in three contexts: +// * By explicitly using std::move() to request it. +// * From a temporary object, since that object cannot be accessed +// afterwards anyway, thus making the state unobservable. +// * On function return, since the object is not observable afterwards. +// +// To sum up: moving from a named object should only be possible with an +// explicit std::move(), or on function return. Moving from a temporary should +// be implicitly done. Moving from a const object is forbidden. +// +// The emulation is not perfect, and has the following shortcomings: +// * move() is not in namespace std. +// * move() is required on function return. +// * There are difficulties with implicit conversions. +// * Microsoft's compiler must be given the /Za switch to successfully compile. +// +// -------------------------- Implementation -------------------------------- // +// The move emulation relies on the peculiar reference binding semantics of +// C++03: as a rule, a non-const reference may not bind to a temporary object, +// except for the implicit object parameter in a member function call, which +// can refer to a temporary even when not being const. +// The moveable object has five important functions to facilitate moving: +// * A private, unimplemented constructor taking a non-const reference to its +// own class. This constructor serves a two-fold purpose. +// - It prevents the creation of a copy constructor that takes a const +// reference. Temporaries would be able to bind to the argument of such a +// constructor, and that would be bad. +// - Named objects will bind to the non-const reference, but since it's +// private, this will fail to compile. This prevents implicit moving from +// named objects. +// There's also a copy assignment operator for the same purpose. +// * An implicit, non-const conversion operator to a special mover type. This +// type represents the rvalue reference of C++0x. Being a non-const member, +// its implicit this parameter can bind to temporaries. +// * A constructor that takes an object of this mover type. This constructor +// performs the actual move operation. There is an equivalent assignment +// operator. +// There is also a free move() function that takes a non-const reference to +// an object and returns a temporary. Internally, this function uses explicit +// constructor calls to move the value from the referenced object to the return +// value. +// +// There are now three possible scenarios of use. +// * Copying from a const object. Constructor overload resolution will find the +// non-const copy constructor, and the move constructor. The first is not +// viable because the const object cannot be bound to the non-const reference. +// The second fails because the conversion to the mover object is non-const. +// Moving from a const object fails as intended. +// * Copying from a named object. Constructor overload resolution will select +// the non-const copy constructor, but fail as intended, because this +// constructor is private. +// * Copying from a temporary. Constructor overload resolution cannot select +// the non-const copy constructor, because the temporary cannot be bound to +// the non-const reference. It thus selects the move constructor. The +// temporary can be bound to the implicit this parameter of the conversion +// operator, because of the special binding rule. Construction succeeds. +// Note that the Microsoft compiler, as an extension, allows binding +// temporaries against non-const references. The compiler thus selects the +// non-const copy constructor and fails, because the constructor is private. +// Passing /Za (disable extensions) disables this behaviour. +// The free move() function is used to move from a named object. +// +// Note that when passing an object of a different type (the classes below +// have OwningResult and OwningPtr, which should be mixable), you get a problem. +// Argument passing and function return use copy initialization rules. The +// effect of this is that, when the source object is not already of the target +// type, the compiler will first seek a way to convert the source object to the +// target type, and only then attempt to copy the resulting object. This means +// that when passing an OwningResult where an OwningPtr is expected, the +// compiler will first seek a conversion from OwningResult to OwningPtr, then +// copy the OwningPtr. The resulting conversion sequence is: +// OwningResult object -> ResultMover -> OwningResult argument to +// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr +// This conversion sequence is too complex to be allowed. Thus the special +// move_* functions, which help the compiler out with some explicit +// conversions. + +// Flip this switch to measure performance impact of the smart pointers. +// #define DISABLE_SMART_POINTERS + +namespace llvm { + template<> + class PointerLikeTypeTraits<clang::ActionBase*> { + typedef clang::ActionBase* PT; + public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; + }; +} + +namespace clang { + // Basic + class DiagnosticBuilder; + + // Determines whether the low bit of the result pointer for the + // given UID is always zero. If so, ActionResult will use that bit + // for it's "invalid" flag. + template<unsigned UID> + struct IsResultPtrLowBitFree { + static const bool value = false; + }; + + /// ActionBase - A small part split from Action because of the horrible + /// definition order dependencies between Action and the smart pointers. + class ActionBase { + public: + /// Out-of-line virtual destructor to provide home for this class. + virtual ~ActionBase(); + + // Types - Though these don't actually enforce strong typing, they document + // what types are required to be identical for the actions. + typedef OpaquePtr<0> DeclPtrTy; + typedef OpaquePtr<1> DeclGroupPtrTy; + typedef OpaquePtr<2> TemplateTy; + typedef void AttrTy; + typedef void BaseTy; + typedef void MemInitTy; + typedef void ExprTy; + typedef void StmtTy; + typedef void TemplateParamsTy; + typedef void CXXScopeTy; + typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>. + + /// ActionResult - This structure is used while parsing/acting on + /// expressions, stmts, etc. It encapsulates both the object returned by + /// the action, plus a sense of whether or not it is valid. + /// When CompressInvalid is true, the "invalid" flag will be + /// stored in the low bit of the Val pointer. + template<unsigned UID, + typename PtrTy = void*, + bool CompressInvalid = IsResultPtrLowBitFree<UID>::value> + class ActionResult { + PtrTy Val; + bool Invalid; + + public: + ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {} + template<typename ActualExprTy> + ActionResult(ActualExprTy val) : Val(val), Invalid(false) {} + ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} + + PtrTy get() const { return Val; } + void set(PtrTy V) { Val = V; } + bool isInvalid() const { return Invalid; } + + const ActionResult &operator=(PtrTy RHS) { + Val = RHS; + Invalid = false; + return *this; + } + }; + + // This ActionResult partial specialization places the "invalid" + // flag into the low bit of the pointer. + template<unsigned UID, typename PtrTy> + class ActionResult<UID, PtrTy, true> { + // A pointer whose low bit is 1 if this result is invalid, 0 + // otherwise. + uintptr_t PtrWithInvalid; + typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; + public: + ActionResult(bool Invalid = false) + : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } + + template<typename ActualExprTy> + ActionResult(ActualExprTy *val) { + PtrTy V(val); + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + ActionResult(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } + + PtrTy get() const { + void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); + return PtrTraits::getFromVoidPointer(VP); + } + + void set(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + bool isInvalid() const { return PtrWithInvalid & 0x01; } + + const ActionResult &operator=(PtrTy RHS) { + void *VP = PtrTraits::getAsVoidPointer(RHS); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + return *this; + } + }; + + /// Deletion callbacks - Since the parser doesn't know the concrete types of + /// the AST nodes being generated, it must do callbacks to delete objects + /// when recovering from errors. These are in ActionBase because the smart + /// pointers need access to them. + virtual void DeleteExpr(ExprTy *E) {} + virtual void DeleteStmt(StmtTy *S) {} + virtual void DeleteTemplateParams(TemplateParamsTy *P) {} + }; + + /// ASTDestroyer - The type of an AST node destruction function pointer. + typedef void (ActionBase::*ASTDestroyer)(void *); + + /// For the transition phase: translate from an ASTDestroyer to its + /// ActionResult UID. + template <ASTDestroyer Destroyer> struct DestroyerToUID; + template <> struct DestroyerToUID<&ActionBase::DeleteExpr> { + static const unsigned UID = 0; + }; + template <> struct DestroyerToUID<&ActionBase::DeleteStmt> { + static const unsigned UID = 1; + }; + /// ASTOwningResult - A moveable smart pointer for AST nodes that also + /// has an extra flag to indicate an additional success status. + template <ASTDestroyer Destroyer> class ASTOwningResult; + + /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns + /// the individual pointers, not the array holding them. + template <ASTDestroyer Destroyer> class ASTMultiPtr; + +#if !defined(DISABLE_SMART_POINTERS) + namespace moving { + /// Move emulation helper for ASTOwningResult. NEVER EVER use this class + /// directly if you don't know what you're doing. + template <ASTDestroyer Destroyer> + class ASTResultMover { + ASTOwningResult<Destroyer> &Moved; + + public: + ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {} + + ASTOwningResult<Destroyer> * operator ->() { return &Moved; } + }; + + /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class + /// directly if you don't know what you're doing. + template <ASTDestroyer Destroyer> + class ASTMultiMover { + ASTMultiPtr<Destroyer> &Moved; + + public: + ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {} + + ASTMultiPtr<Destroyer> * operator ->() { return &Moved; } + + /// Reset the moved object's internal structures. + void release(); + }; + } +#else + + /// Kept only as a type-safe wrapper for a void pointer, when smart pointers + /// are disabled. When they are enabled, ASTOwningResult takes over. + template <ASTDestroyer Destroyer> + class ASTOwningPtr { + void *Node; + + public: + explicit ASTOwningPtr(ActionBase &) : Node(0) {} + ASTOwningPtr(ActionBase &, void *node) : Node(node) {} + // Normal copying operators are defined implicitly. + ASTOwningPtr(const ASTOwningResult<Destroyer> &o); + + ASTOwningPtr & operator =(void *raw) { + Node = raw; + return *this; + } + + /// Access to the raw pointer. + void * get() const { return Node; } + + /// Release the raw pointer. + void * take() { + return Node; + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(Node); + } + + /// Alias for interface familiarity with unique_ptr. + void * release() { + return take(); + } + }; +#endif + + // Important: There are two different implementations of + // ASTOwningResult below, depending on whether + // DISABLE_SMART_POINTERS is defined. If you make changes that + // affect the interface, be sure to compile and test both ways! + +#if !defined(DISABLE_SMART_POINTERS) + template <ASTDestroyer Destroyer> + class ASTOwningResult { + llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv; + void *Ptr; + + friend class moving::ASTResultMover<Destroyer>; + +#if !(defined(_MSC_VER) && _MSC_VER >= 1600) + ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT + ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT +#endif + + void destroy() { + if (Ptr) { + assert(ActionInv.getPointer() && + "Smart pointer has node but no action."); + (ActionInv.getPointer()->*Destroyer)(Ptr); + Ptr = 0; + } + } + + public: + typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; + + explicit ASTOwningResult(ActionBase &actions, bool invalid = false) + : ActionInv(&actions, invalid), Ptr(0) {} + ASTOwningResult(ActionBase &actions, void *node) + : ActionInv(&actions, false), Ptr(node) {} + ASTOwningResult(ActionBase &actions, const DumbResult &res) + : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {} + /// Move from another owning result + ASTOwningResult(moving::ASTResultMover<Destroyer> mover) + : ActionInv(mover->ActionInv), + Ptr(mover->Ptr) { + mover->Ptr = 0; + } + + ~ASTOwningResult() { + destroy(); + } + + /// Move assignment from another owning result + ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) { + destroy(); + ActionInv = mover->ActionInv; + Ptr = mover->Ptr; + mover->Ptr = 0; + return *this; + } + +#if defined(_MSC_VER) && _MSC_VER >= 1600 + // Emulated move semantics don't work with msvc. + ASTOwningResult(ASTOwningResult &&mover) + : ActionInv(mover.ActionInv), + Ptr(mover.Ptr) { + mover.Ptr = 0; + } + ASTOwningResult &operator=(ASTOwningResult &&mover) { + *this = moving::ASTResultMover<Destroyer>(mover); + return *this; + } +#endif + + /// Assignment from a raw pointer. Takes ownership - beware! + ASTOwningResult &operator=(void *raw) { + destroy(); + Ptr = raw; + ActionInv.setInt(false); + return *this; + } + + /// Assignment from an ActionResult. Takes ownership - beware! + ASTOwningResult &operator=(const DumbResult &res) { + destroy(); + Ptr = res.get(); + ActionInv.setInt(res.isInvalid()); + return *this; + } + + /// Access to the raw pointer. + void *get() const { return Ptr; } + + bool isInvalid() const { return ActionInv.getInt(); } + + /// Does this point to a usable AST node? To be usable, the node must be + /// valid and non-null. + bool isUsable() const { return !isInvalid() && get(); } + + /// Take outside ownership of the raw pointer. + void *take() { + if (isInvalid()) + return 0; + void *tmp = Ptr; + Ptr = 0; + return tmp; + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(take()); + } + + /// Alias for interface familiarity with unique_ptr. + void *release() { return take(); } + + /// Pass ownership to a classical ActionResult. + DumbResult result() { + if (isInvalid()) + return true; + return take(); + } + + /// Move hook + operator moving::ASTResultMover<Destroyer>() { + return moving::ASTResultMover<Destroyer>(*this); + } + }; +#else + template <ASTDestroyer Destroyer> + class ASTOwningResult { + public: + typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; + + private: + DumbResult Result; + + public: + explicit ASTOwningResult(ActionBase &actions, bool invalid = false) + : Result(invalid) { } + ASTOwningResult(ActionBase &actions, void *node) : Result(node) { } + ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { } + // Normal copying semantics are defined implicitly. + ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { } + + /// Assignment from a raw pointer. Takes ownership - beware! + ASTOwningResult & operator =(void *raw) { + Result = raw; + return *this; + } + + /// Assignment from an ActionResult. Takes ownership - beware! + ASTOwningResult & operator =(const DumbResult &res) { + Result = res; + return *this; + } + + /// Access to the raw pointer. + void * get() const { return Result.get(); } + + bool isInvalid() const { return Result.isInvalid(); } + + /// Does this point to a usable AST node? To be usable, the node must be + /// valid and non-null. + bool isUsable() const { return !Result.isInvalid() && get(); } + + /// Take outside ownership of the raw pointer. + void * take() { + return Result.get(); + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(take()); + } + + /// Alias for interface familiarity with unique_ptr. + void * release() { return take(); } + + /// Pass ownership to a classical ActionResult. + DumbResult result() { return Result; } + }; +#endif + + template <ASTDestroyer Destroyer> + class ASTMultiPtr { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; +#endif + void **Nodes; + unsigned Count; + +#if !defined(DISABLE_SMART_POINTERS) + friend class moving::ASTMultiMover<Destroyer>; + +#if defined(_MSC_VER) + // Last tested with Visual Studio 2008. + // Visual C++ appears to have a bug where it does not recognise + // the return value from ASTMultiMover<Destroyer>::opeator-> as + // being a pointer to ASTMultiPtr. However, the diagnostics + // suggest it has the right name, simply that the pointer type + // is not convertible to itself. + // Either way, a classic C-style hard cast resolves any issue. + static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) { + return (ASTMultiPtr*)source.operator->(); + } +#endif + + ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT + // Reference member prevents copy assignment. + + void destroy() { + assert((Count == 0 || Nodes) && "No nodes when count is not zero."); + for (unsigned i = 0; i < Count; ++i) { + if (Nodes[i]) + (Actions.*Destroyer)(Nodes[i]); + } + } +#endif + + public: +#if !defined(DISABLE_SMART_POINTERS) + explicit ASTMultiPtr(ActionBase &actions) + : Actions(actions), Nodes(0), Count(0) {} + ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count) + : Actions(actions), Nodes(nodes), Count(count) {} + /// Move constructor + ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover) +#if defined(_MSC_VER) + // Apply the visual C++ hack supplied above. + // Last tested with Visual Studio 2008. + : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) { +#else + : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) { +#endif + mover.release(); + } +#else + // Normal copying implicitly defined + explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {} + ASTMultiPtr(ActionBase &, void **nodes, unsigned count) + : Nodes(nodes), Count(count) {} + // Fake mover in Parse/AstGuard.h needs this: + ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {} +#endif + +#if !defined(DISABLE_SMART_POINTERS) + /// Move assignment + ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) { + destroy(); + Nodes = mover->Nodes; + Count = mover->Count; + mover.release(); + return *this; + } +#endif + + /// Access to the raw pointers. + void ** get() const { return Nodes; } + + /// Access to the count. + unsigned size() const { return Count; } + + void ** release() { +#if !defined(DISABLE_SMART_POINTERS) + void **tmp = Nodes; + Nodes = 0; + Count = 0; + return tmp; +#else + return Nodes; +#endif + } + +#if !defined(DISABLE_SMART_POINTERS) + /// Move hook + operator moving::ASTMultiMover<Destroyer>() { + return moving::ASTMultiMover<Destroyer>(*this); + } +#endif + }; + + class ParsedTemplateArgument; + + class ASTTemplateArgsPtr { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; +#endif + ParsedTemplateArgument *Args; + mutable unsigned Count; + +#if !defined(DISABLE_SMART_POINTERS) + void destroy(); +#endif + + public: + ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args, + unsigned count) : +#if !defined(DISABLE_SMART_POINTERS) + Actions(actions), +#endif + Args(args), Count(count) { } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : +#if !defined(DISABLE_SMART_POINTERS) + Actions(Other.Actions), +#endif + Args(Other.Args), Count(Other.Count) { +#if !defined(DISABLE_SMART_POINTERS) + Other.Count = 0; +#endif + } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { +#if !defined(DISABLE_SMART_POINTERS) + Actions = Other.Actions; +#endif + Args = Other.Args; + Count = Other.Count; +#if !defined(DISABLE_SMART_POINTERS) + Other.Count = 0; +#endif + return *this; + } + +#if !defined(DISABLE_SMART_POINTERS) + ~ASTTemplateArgsPtr() { destroy(); } +#endif + + ParsedTemplateArgument *getArgs() const { return Args; } + unsigned size() const { return Count; } + + void reset(ParsedTemplateArgument *args, unsigned count) { +#if !defined(DISABLE_SMART_POINTERS) + destroy(); +#endif + Args = args; + Count = count; + } + + const ParsedTemplateArgument &operator[](unsigned Arg) const; + + ParsedTemplateArgument *release() const { +#if !defined(DISABLE_SMART_POINTERS) + Count = 0; +#endif + return Args; + } + }; + + /// \brief A small vector that owns a set of AST nodes. + template <ASTDestroyer Destroyer, unsigned N = 8> + class ASTOwningVector : public llvm::SmallVector<void *, N> { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; + bool Owned; +#endif + + ASTOwningVector(ASTOwningVector &); // do not implement + ASTOwningVector &operator=(ASTOwningVector &); // do not implement + + public: + explicit ASTOwningVector(ActionBase &Actions) +#if !defined(DISABLE_SMART_POINTERS) + : Actions(Actions), Owned(true) +#endif + { } + +#if !defined(DISABLE_SMART_POINTERS) + ~ASTOwningVector() { + if (!Owned) + return; + + for (unsigned I = 0, Last = this->size(); I != Last; ++I) + (Actions.*Destroyer)((*this)[I]); + } +#endif + + void **take() { +#if !defined(DISABLE_SMART_POINTERS) + Owned = false; +#endif + return &this->front(); + } + + template<typename T> T **takeAs() { return (T**)take(); } + +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &getActions() const { return Actions; } +#endif + }; + + /// A SmallVector of statements, with stack size 32 (as that is the only one + /// used.) + typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector; + /// A SmallVector of expressions, with stack size 12 (the maximum used.) + typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector; + + template <ASTDestroyer Destroyer, unsigned N> inline + ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) { +#if !defined(DISABLE_SMART_POINTERS) + return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size()); +#else + return ASTMultiPtr<Destroyer>(vec.take(), vec.size()); +#endif + } + +#if !defined(DISABLE_SMART_POINTERS) + + // Out-of-line implementations due to definition dependencies + + template <ASTDestroyer Destroyer> inline + void moving::ASTMultiMover<Destroyer>::release() { + Moved.Nodes = 0; + Moved.Count = 0; + } + + // Move overloads. + + template <ASTDestroyer Destroyer> inline + ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) { + return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr)); + } + + template <ASTDestroyer Destroyer> inline + ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) { + return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr)); + } + +#else + + template <ASTDestroyer Destroyer> inline + ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o) + : Node(o.get()) { } + + // These versions are hopefully no-ops. + template <ASTDestroyer Destroyer> inline + ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) { + return ptr; + } + + template <ASTDestroyer Destroyer> inline + ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) { + return ptr; + } + + template <ASTDestroyer Destroyer> inline + ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) { + return ptr; + } +#endif +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h new file mode 100644 index 0000000..d7c5eee --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- 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_DIAGNOSTICPARSE_H +#define LLVM_CLANG_DIAGNOSTICPARSE_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define PARSESTART +#include "clang/Basic/DiagnosticParseKinds.inc" +#undef DIAG + NUM_BUILTIN_PARSE_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h new file mode 100644 index 0000000..8081c24 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h @@ -0,0 +1,1503 @@ +//===--- Parser.h - C Language Parser ---------------------------*- 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 Parser interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_PARSER_H +#define LLVM_CLANG_PARSE_PARSER_H + +#include "clang/Basic/Specifiers.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/Action.h" +#include "clang/Parse/DeclSpec.h" +#include "llvm/ADT/OwningPtr.h" +#include <stack> +#include <list> + +namespace clang { + class AttributeList; + struct CXX0XAttributeList; + class PragmaHandler; + class Scope; + class DiagnosticBuilder; + class Parser; + class PragmaUnusedHandler; + class ColonProtectionRAIIObject; + +/// PrettyStackTraceParserEntry - If a crash happens while the parser is active, +/// an entry is printed for it. +class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { + const Parser &P; +public: + PrettyStackTraceParserEntry(const Parser &p) : P(p) {} + virtual void print(llvm::raw_ostream &OS) const; +}; + +/// PrecedenceLevels - These are precedences for the binary/ternary +/// operators in the C99 grammar. These have been named to relate +/// with the C99 grammar productions. Low precedences numbers bind +/// more weakly than high numbers. +namespace prec { + enum Level { + Unknown = 0, // Not binary operator. + Comma = 1, // , + Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= + Conditional = 3, // ? + LogicalOr = 4, // || + LogicalAnd = 5, // && + InclusiveOr = 6, // | + ExclusiveOr = 7, // ^ + And = 8, // & + Equality = 9, // ==, != + Relational = 10, // >=, <=, >, < + Shift = 11, // <<, >> + Additive = 12, // -, + + Multiplicative = 13, // *, /, % + PointerToMember = 14 // .*, ->* + }; +} + +/// Parser - This implements a parser for the C family of languages. After +/// parsing units of the grammar, productions are invoked to handle whatever has +/// been read. +/// +class Parser { + friend class PragmaUnusedHandler; + friend class ColonProtectionRAIIObject; + PrettyStackTraceParserEntry CrashInfo; + + Preprocessor &PP; + + /// Tok - The current token we are peeking ahead. All parsing methods assume + /// that this is valid. + Token Tok; + + // PrevTokLocation - The location of the token we previously + // consumed. This token is used for diagnostics where we expected to + // see a token following another token (e.g., the ';' at the end of + // a statement). + SourceLocation PrevTokLocation; + + unsigned short ParenCount, BracketCount, BraceCount; + + /// Actions - These are the callbacks we invoke as we parse various constructs + /// in the file. This refers to the common base class between MinimalActions + /// and SemaActions for those uses that don't matter. + Action &Actions; + + Scope *CurScope; + Diagnostic &Diags; + + /// ScopeCache - Cache scopes to reduce malloc traffic. + enum { ScopeCacheSize = 16 }; + unsigned NumCachedScopes; + Scope *ScopeCache[ScopeCacheSize]; + + /// Ident_super - IdentifierInfo for "super", to support fast + /// comparison. + IdentifierInfo *Ident_super; + /// Ident_vector and Ident_pixel - cached IdentifierInfo's for + /// "vector" and "pixel" fast comparison. Only present if + /// AltiVec enabled. + IdentifierInfo *Ident_vector; + IdentifierInfo *Ident_pixel; + + llvm::OwningPtr<PragmaHandler> OptionsHandler; + llvm::OwningPtr<PragmaHandler> PackHandler; + llvm::OwningPtr<PragmaHandler> UnusedHandler; + llvm::OwningPtr<PragmaHandler> WeakHandler; + + /// 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; + + /// The "depth" of the template parameters currently being parsed. + unsigned TemplateParameterDepth; + +public: + Parser(Preprocessor &PP, Action &Actions); + ~Parser(); + + const LangOptions &getLang() const { return PP.getLangOptions(); } + const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } + Preprocessor &getPreprocessor() const { return PP; } + Action &getActions() const { return Actions; } + + const Token &getCurToken() const { return Tok; } + + // Type forwarding. All of these are statically 'void*', but they may all be + // different actual classes based on the actions in place. + typedef Action::ExprTy ExprTy; + typedef Action::StmtTy StmtTy; + typedef Action::DeclPtrTy DeclPtrTy; + typedef Action::DeclGroupPtrTy DeclGroupPtrTy; + typedef Action::TypeTy TypeTy; + typedef Action::BaseTy BaseTy; + typedef Action::MemInitTy MemInitTy; + typedef Action::CXXScopeTy CXXScopeTy; + typedef Action::TemplateParamsTy TemplateParamsTy; + typedef Action::TemplateTy TemplateTy; + + typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists; + + typedef Action::ExprResult ExprResult; + typedef Action::StmtResult StmtResult; + typedef Action::BaseResult BaseResult; + typedef Action::MemInitResult MemInitResult; + typedef Action::TypeResult TypeResult; + + typedef Action::OwningExprResult OwningExprResult; + typedef Action::OwningStmtResult OwningStmtResult; + + typedef Action::ExprArg ExprArg; + typedef Action::MultiStmtArg MultiStmtArg; + typedef Action::FullExprArg FullExprArg; + + /// Adorns a ExprResult with Actions to make it an OwningExprResult + OwningExprResult Owned(ExprResult res) { + return OwningExprResult(Actions, res); + } + /// Adorns a StmtResult with Actions to make it an OwningStmtResult + OwningStmtResult Owned(StmtResult res) { + return OwningStmtResult(Actions, res); + } + + OwningExprResult ExprError() { return OwningExprResult(Actions, true); } + OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); } + + OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); } + OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); } + + OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); } + + // Parsing methods. + + /// ParseTranslationUnit - All in one method that initializes parses, and + /// shuts down the parser. + void ParseTranslationUnit(); + + /// Initialize - Warm up the parser. + /// + void Initialize(); + + /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if + /// the EOF was encountered. + bool ParseTopLevelDecl(DeclGroupPtrTy &Result); + + DeclGroupPtrTy RetrievePendingObjCImpDecl(); + +private: + //===--------------------------------------------------------------------===// + // Low-Level token peeking and consumption methods. + // + + /// isTokenParen - Return true if the cur token is '(' or ')'. + bool isTokenParen() const { + return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren; + } + /// isTokenBracket - Return true if the cur token is '[' or ']'. + bool isTokenBracket() const { + return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square; + } + /// isTokenBrace - Return true if the cur token is '{' or '}'. + bool isTokenBrace() const { + return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace; + } + + /// isTokenStringLiteral - True if this token is a string-literal. + /// + bool isTokenStringLiteral() const { + return Tok.getKind() == tok::string_literal || + Tok.getKind() == tok::wide_string_literal; + } + + /// ConsumeToken - Consume the current 'peek token' and lex the next one. + /// This does not work with all kinds of tokens: strings and specific other + /// tokens must be consumed with custom methods below. This returns the + /// location of the consumed token. + SourceLocation ConsumeToken() { + assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && + !isTokenBrace() && + "Should consume special tokens with Consume*Token"); + if (Tok.is(tok::code_completion)) { + CodeCompletionRecovery(); + return ConsumeCodeCompletionToken(); + } + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeAnyToken - Dispatch to the right Consume* method based on the + /// current token type. This should only be used in cases where the type of + /// the token really isn't known, e.g. in error recovery. + SourceLocation ConsumeAnyToken() { + if (isTokenParen()) + return ConsumeParen(); + else if (isTokenBracket()) + return ConsumeBracket(); + else if (isTokenBrace()) + return ConsumeBrace(); + else if (isTokenStringLiteral()) + return ConsumeStringToken(); + else + return ConsumeToken(); + } + + /// ConsumeParen - This consume method keeps the paren count up-to-date. + /// + SourceLocation ConsumeParen() { + assert(isTokenParen() && "wrong consume method"); + if (Tok.getKind() == tok::l_paren) + ++ParenCount; + else if (ParenCount) + --ParenCount; // Don't let unbalanced )'s drive the count negative. + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeBracket - This consume method keeps the bracket count up-to-date. + /// + SourceLocation ConsumeBracket() { + assert(isTokenBracket() && "wrong consume method"); + if (Tok.getKind() == tok::l_square) + ++BracketCount; + else if (BracketCount) + --BracketCount; // Don't let unbalanced ]'s drive the count negative. + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeBrace - This consume method keeps the brace count up-to-date. + /// + SourceLocation ConsumeBrace() { + assert(isTokenBrace() && "wrong consume method"); + if (Tok.getKind() == tok::l_brace) + ++BraceCount; + else if (BraceCount) + --BraceCount; // Don't let unbalanced }'s drive the count negative. + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeStringToken - Consume the current 'peek token', lexing a new one + /// and returning the token kind. This method is specific to strings, as it + /// handles string literal concatenation, as per C99 5.1.1.2, translation + /// phase #6. + SourceLocation ConsumeStringToken() { + assert(isTokenStringLiteral() && + "Should only consume string literals with this method"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// \brief Consume the current code-completion token. + /// + /// This routine should be called to consume the code-completion token once + /// a code-completion action has already been invoked. + SourceLocation ConsumeCodeCompletionToken() { + assert(Tok.is(tok::code_completion)); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + ///\ brief When we are consuming a code-completion token within having + /// matched specific position in the grammar, provide code-completion results + /// based on context. + void CodeCompletionRecovery(); + + /// 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. + /// + /// Note that this differs from the Preprocessor's LookAhead method, because + /// the Parser always has one token lexed that the preprocessor doesn't. + /// + const Token &GetLookAheadToken(unsigned N) { + if (N == 0 || Tok.is(tok::eof)) return Tok; + return PP.LookAhead(N-1); + } + + /// NextToken - This peeks ahead one token and returns it without + /// consuming it. + const Token &NextToken() { + return PP.LookAhead(0); + } + + /// TryAnnotateTypeOrScopeToken - If the current token position is on a + /// typename (possibly qualified in C++) or a C++ scope specifier not followed + /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens + /// with a single annotation token representing the typename or C++ scope + /// respectively. + /// This simplifies handling of C++ scope specifiers and allows efficient + /// backtracking without the need to re-parse and resolve nested-names and + /// typenames. + /// It will mainly be called when we expect to treat identifiers as typenames + /// (if they are typenames). For example, in C we do not expect identifiers + /// inside expressions to be treated as typenames so it will not be called + /// for expressions in C. + /// + /// This returns true if the token was annotated. + bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false); + + /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but + /// only annotates C++ scope specifiers. This returns true if there + /// was an unrecoverable error. + bool TryAnnotateCXXScopeToken(bool EnteringContext = false); + + /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens, + /// replacing them with the non-context-sensitive keywords. This returns + /// true if the token was replaced. + bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid) { + if (!getLang().AltiVec || + (Tok.getIdentifierInfo() != Ident_vector && + Tok.getIdentifierInfo() != Ident_pixel)) + return false; + + return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid); + } + + /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector + /// identifier token, replacing it with the non-context-sensitive __vector. + /// This returns true if the token was replaced. + bool TryAltiVecVectorToken() { + if (!getLang().AltiVec || + Tok.getIdentifierInfo() != Ident_vector) return false; + return TryAltiVecVectorTokenOutOfLine(); + } + + bool TryAltiVecVectorTokenOutOfLine(); + bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid); + + /// TentativeParsingAction - An object that is used as a kind of "tentative + /// parsing transaction". It gets instantiated to mark the token position and + /// after the token consumption is done, Commit() or Revert() is called to + /// either "commit the consumed tokens" or revert to the previously marked + /// token position. Example: + /// + /// TentativeParsingAction TPA(*this); + /// ConsumeToken(); + /// .... + /// TPA.Revert(); + /// + class TentativeParsingAction { + Parser &P; + Token PrevTok; + bool isActive; + + public: + explicit TentativeParsingAction(Parser& p) : P(p) { + PrevTok = P.Tok; + P.PP.EnableBacktrackAtThisPos(); + isActive = true; + } + void Commit() { + assert(isActive && "Parsing action was finished!"); + P.PP.CommitBacktrackedTokens(); + isActive = false; + } + void Revert() { + assert(isActive && "Parsing action was finished!"); + P.PP.Backtrack(); + P.Tok = PrevTok; + isActive = false; + } + ~TentativeParsingAction() { + assert(!isActive && "Forgot to call Commit or Revert!"); + } + }; + + + /// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'), + /// this helper function matches and consumes the specified RHS token if + /// present. If not present, it emits the specified diagnostic indicating + /// that the parser failed to match the RHS of the token at LHSLoc. LHSName + /// should be the name of the unmatched LHS token. This returns the location + /// of the consumed token. + SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok, + SourceLocation LHSLoc); + + /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the + /// input. If so, it is consumed and false is returned. + /// + /// If the input is malformed, this emits the specified diagnostic. Next, if + /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is + /// returned. + bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag, + const char *DiagMsg = "", + tok::TokenKind SkipToTok = tok::unknown); + + //===--------------------------------------------------------------------===// + // Scope manipulation + + /// ParseScope - Introduces a new scope for parsing. The kind of + /// scope is determined by ScopeFlags. Objects of this type should + /// be created on the stack to coincide with the position where the + /// parser enters the new scope, and this object's constructor will + /// create that new scope. Similarly, once the object is destroyed + /// the parser will exit the scope. + class ParseScope { + Parser *Self; + ParseScope(const ParseScope&); // do not implement + ParseScope& operator=(const ParseScope&); // do not implement + + public: + // ParseScope - Construct a new object to manage a scope in the + // parser Self where the new Scope is created with the flags + // ScopeFlags, but only when ManageScope is true (the default). If + // ManageScope is false, this object does nothing. + ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true) + : Self(Self) { + if (ManageScope) + Self->EnterScope(ScopeFlags); + else + this->Self = 0; + } + + // Exit - Exit the scope associated with this object now, rather + // than waiting until the object is destroyed. + void Exit() { + if (Self) { + Self->ExitScope(); + Self = 0; + } + } + + ~ParseScope() { + Exit(); + } + }; + + /// EnterScope - Start a new scope. + void EnterScope(unsigned ScopeFlags); + + /// ExitScope - Pop a scope off the scope stack. + void ExitScope(); + + //===--------------------------------------------------------------------===// + // Diagnostic Emission and Error recovery. + +public: + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID); + +private: + void SuggestParentheses(SourceLocation Loc, unsigned DK, + SourceRange ParenRange); + + /// SkipUntil - Read tokens until we get to the specified token, then consume + /// it (unless DontConsume is true). Because we cannot guarantee that the + /// token will ever occur, this skips to the next token, or to some likely + /// good stopping point. If StopAtSemi is true, skipping will stop at a ';' + /// character. + /// + /// If SkipUntil finds the specified token, it returns true, otherwise it + /// returns false. + bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true, + bool DontConsume = false) { + return SkipUntil(&T, 1, StopAtSemi, DontConsume); + } + bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true, + bool DontConsume = false) { + tok::TokenKind TokArray[] = {T1, T2}; + return SkipUntil(TokArray, 2, StopAtSemi, DontConsume); + } + bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, + bool StopAtSemi = true, bool DontConsume = false); + + //===--------------------------------------------------------------------===// + // Lexing and parsing of C++ inline methods. + + struct LexedMethod { + Action::DeclPtrTy D; + CachedTokens Toks; + + /// \brief Whether this member function had an associated template + /// scope. When true, D is a template declaration. + /// othewise, it is a member function declaration. + bool TemplateScope; + + explicit LexedMethod(Action::DeclPtrTy MD) : D(MD), TemplateScope(false) {} + }; + + /// LateParsedDefaultArgument - Keeps track of a parameter that may + /// have a default argument that cannot be parsed yet because it + /// occurs within a member function declaration inside the class + /// (C++ [class.mem]p2). + struct LateParsedDefaultArgument { + explicit LateParsedDefaultArgument(Action::DeclPtrTy P, + CachedTokens *Toks = 0) + : Param(P), Toks(Toks) { } + + /// Param - The parameter declaration for this parameter. + Action::DeclPtrTy Param; + + /// Toks - The sequence of tokens that comprises the default + /// argument expression, not including the '=' or the terminating + /// ')' or ','. This will be NULL for parameters that have no + /// default argument. + CachedTokens *Toks; + }; + + /// LateParsedMethodDeclaration - A method declaration inside a class that + /// contains at least one entity whose parsing needs to be delayed + /// until the class itself is completely-defined, such as a default + /// argument (C++ [class.mem]p2). + struct LateParsedMethodDeclaration { + explicit LateParsedMethodDeclaration(Action::DeclPtrTy M) + : Method(M), TemplateScope(false) { } + + /// Method - The method declaration. + Action::DeclPtrTy Method; + + /// \brief Whether this member function had an associated template + /// scope. When true, D is a template declaration. + /// othewise, it is a member function declaration. + bool TemplateScope; + + /// DefaultArgs - Contains the parameters of the function and + /// their default arguments. At least one of the parameters will + /// have a default argument, but all of the parameters of the + /// method will be stored so that they can be reintroduced into + /// scope at the appropriate times. + llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs; + }; + + /// LateParsedMethodDecls - During parsing of a top (non-nested) C++ + /// class, its method declarations that contain parts that won't be + /// parsed until after the definiton is completed (C++ [class.mem]p2), + /// the method declarations will be stored here with the tokens that + /// will be parsed to create those entities. + typedef std::list<LateParsedMethodDeclaration> LateParsedMethodDecls; + + /// LexedMethodsForTopClass - During parsing of a top (non-nested) C++ class, + /// its inline method definitions and the inline method definitions of its + /// nested classes are lexed and stored here. + typedef std::list<LexedMethod> LexedMethodsForTopClass; + + /// \brief Representation of a class that has been parsed, including + /// any member function declarations or definitions that need to be + /// parsed after the corresponding top-level class is complete. + struct ParsingClass { + ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass) + : TopLevelClass(TopLevelClass), TemplateScope(false), + TagOrTemplate(TagOrTemplate) { } + + /// \brief Whether this is a "top-level" class, meaning that it is + /// not nested within another class. + bool TopLevelClass : 1; + + /// \brief Whether this class had an associated template + /// scope. When true, TagOrTemplate is a template declaration; + /// othewise, it is a tag declaration. + bool TemplateScope : 1; + + /// \brief The class or class template whose definition we are parsing. + DeclPtrTy TagOrTemplate; + + /// MethodDecls - Method declarations that contain pieces whose + /// parsing will be delayed until the class is fully defined. + LateParsedMethodDecls MethodDecls; + + /// MethodDefs - Methods whose definitions will be parsed once the + /// class has been fully defined. + LexedMethodsForTopClass MethodDefs; + + /// \brief Nested classes inside this class. + llvm::SmallVector<ParsingClass*, 4> NestedClasses; + }; + + /// \brief The stack of classes that is currently being + /// parsed. Nested and local classes will be pushed onto this stack + /// when they are parsed, and removed afterward. + std::stack<ParsingClass *> ClassStack; + + ParsingClass &getCurrentClass() { + assert(!ClassStack.empty() && "No lexed method stacks!"); + return *ClassStack.top(); + } + + /// \brief RAII object used to inform the actions that we're + /// currently parsing a declaration. This is active when parsing a + /// variable's initializer, but not when parsing the body of a + /// class or function definition. + class ParsingDeclRAIIObject { + Action &Actions; + Action::ParsingDeclStackState State; + bool Popped; + + public: + ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) { + push(); + } + + ~ParsingDeclRAIIObject() { + abort(); + } + + /// Resets the RAII object for a new declaration. + void reset() { + abort(); + push(); + } + + /// Signals that the context was completed without an appropriate + /// declaration being parsed. + void abort() { + pop(DeclPtrTy()); + } + + void complete(DeclPtrTy D) { + assert(!Popped && "ParsingDeclaration has already been popped!"); + pop(D); + } + + private: + void push() { + State = Actions.PushParsingDeclaration(); + Popped = false; + } + + void pop(DeclPtrTy D) { + if (!Popped) { + Actions.PopParsingDeclaration(State, D); + Popped = true; + } + } + }; + + /// A class for parsing a DeclSpec. + class ParsingDeclSpec : public DeclSpec { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclSpec(Parser &P) : ParsingRAII(P) { + } + + void complete(DeclPtrTy D) { + ParsingRAII.complete(D); + } + + void abort() { + ParsingRAII.abort(); + } + }; + + /// A class for parsing a declarator. + class ParsingDeclarator : public Declarator { + ParsingDeclRAIIObject ParsingRAII; + + public: + ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) + : Declarator(DS, C), ParsingRAII(P) { + } + + const ParsingDeclSpec &getDeclSpec() const { + return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); + } + + ParsingDeclSpec &getMutableDeclSpec() const { + return const_cast<ParsingDeclSpec&>(getDeclSpec()); + } + + void clear() { + Declarator::clear(); + ParsingRAII.reset(); + } + + void complete(DeclPtrTy D) { + ParsingRAII.complete(D); + } + }; + + /// \brief RAII object used to + class ParsingClassDefinition { + Parser &P; + bool Popped; + + public: + ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass) + : P(P), Popped(false) { + P.PushParsingClass(TagOrTemplate, TopLevelClass); + } + + /// \brief Pop this class of the stack. + void Pop() { + assert(!Popped && "Nested class has already been popped"); + Popped = true; + P.PopParsingClass(); + } + + ~ParsingClassDefinition() { + if (!Popped) + P.PopParsingClass(); + } + }; + + /// \brief Contains information about any template-specific + /// information that has been parsed prior to parsing declaration + /// specifiers. + struct ParsedTemplateInfo { + ParsedTemplateInfo() + : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { } + + ParsedTemplateInfo(TemplateParameterLists *TemplateParams, + bool isSpecialization, + bool lastParameterListWasEmpty = false) + : Kind(isSpecialization? ExplicitSpecialization : Template), + TemplateParams(TemplateParams), + LastParameterListWasEmpty(lastParameterListWasEmpty) { } + + explicit ParsedTemplateInfo(SourceLocation ExternLoc, + SourceLocation TemplateLoc) + : Kind(ExplicitInstantiation), TemplateParams(0), + ExternLoc(ExternLoc), TemplateLoc(TemplateLoc), + LastParameterListWasEmpty(false){ } + + /// \brief The kind of template we are parsing. + enum { + /// \brief We are not parsing a template at all. + NonTemplate = 0, + /// \brief We are parsing a template declaration. + Template, + /// \brief We are parsing an explicit specialization. + ExplicitSpecialization, + /// \brief We are parsing an explicit instantiation. + ExplicitInstantiation + } Kind; + + /// \brief The template parameter lists, for template declarations + /// and explicit specializations. + TemplateParameterLists *TemplateParams; + + /// \brief The location of the 'extern' keyword, if any, for an explicit + /// instantiation + SourceLocation ExternLoc; + + /// \brief The location of the 'template' keyword, for an explicit + /// instantiation. + SourceLocation TemplateLoc; + + /// \brief Whether the last template parameter list was empty. + bool LastParameterListWasEmpty; + }; + + void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass); + void DeallocateParsedClasses(ParsingClass *Class); + void PopParsingClass(); + + DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, + const ParsedTemplateInfo &TemplateInfo); + void ParseLexedMethodDeclarations(ParsingClass &Class); + void ParseLexedMethodDefs(ParsingClass &Class); + bool ConsumeAndStoreUntil(tok::TokenKind T1, + CachedTokens &Toks, + bool StopAtSemi = true, + bool ConsumeFinalToken = true) { + return ConsumeAndStoreUntil(T1, T1, Toks, StopAtSemi, ConsumeFinalToken); + } + bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, + CachedTokens &Toks, + bool StopAtSemi = true, + bool ConsumeFinalToken = true); + + //===--------------------------------------------------------------------===// + // C99 6.9: External Definitions. + DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr); + bool isDeclarationAfterDeclarator(); + bool isStartOfFunctionDefinition(); + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, + AccessSpecifier AS = AS_none); + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, + AttributeList *Attr, + AccessSpecifier AS = AS_none); + + DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + void ParseKNRParamDeclarations(Declarator &D); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the simple-asm. + OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); + OwningExprResult ParseAsmStringLiteral(); + + // Objective-C External Declarations + DeclPtrTy ParseObjCAtDirectives(); + DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, + AttributeList *prefixAttrs = 0); + void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind visibility, + SourceLocation atLoc); + bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P, + llvm::SmallVectorImpl<SourceLocation> &PLocs, + bool WarnOnDeclarations, + SourceLocation &LAngleLoc, + SourceLocation &EndProtoLoc); + void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind contextKey); + DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc, + AttributeList *prefixAttrs = 0); + + DeclPtrTy ObjCImpDecl; + llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl; + + DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd); + DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc); + DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc); + + IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation); + // Definitions for Objective-c context sensitive keywords recognition. + enum ObjCTypeQual { + objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref, + objc_NumQuals + }; + IdentifierInfo *ObjCTypeQuals[objc_NumQuals]; + + bool isTokIdentifier_in() const; + + TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS); + void ParseObjCMethodRequirement(); + DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat, + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, + DeclPtrTy classDecl, + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, unsigned NumMethods); + + DeclPtrTy ParseObjCMethodDefinition(); + + //===--------------------------------------------------------------------===// + // C99 6.5: Expressions. + + OwningExprResult ParseExpression(); + OwningExprResult ParseConstantExpression(); + // Expr that doesn't include commas. + OwningExprResult ParseAssignmentExpression(); + + OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); + + OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); + + OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS, + prec::Level MinPrec); + OwningExprResult ParseCastExpression(bool isUnaryExpression, + bool isAddressOfOperand, + bool &NotCastExpr, + TypeTy *TypeOfCast); + OwningExprResult ParseCastExpression(bool isUnaryExpression, + bool isAddressOfOperand = false, + TypeTy *TypeOfCast = 0); + OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS); + OwningExprResult ParseSizeofAlignofExpression(); + OwningExprResult ParseBuiltinPrimaryExpression(); + + OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, + bool &isCastExpr, + TypeTy *&CastTy, + SourceRange &CastRange); + + static const unsigned ExprListSize = 12; + typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy; + typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy; + + /// ParseExpressionList - Used for C/C++ (argument-)expression-list. + bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs, + void (Action::*Completer)(Scope *S, void *Data, + ExprTy **Args, + unsigned NumArgs) = 0, + void *Data = 0); + + /// ParenParseOption - Control what ParseParenExpression will parse. + enum ParenParseOption { + SimpleExpr, // Only parse '(' expression ')' + CompoundStmt, // Also allow '(' compound-statement ')' + CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}' + CastExpr // Also allow '(' type-name ')' <anything> + }; + OwningExprResult ParseParenExpression(ParenParseOption &ExprType, + bool stopIfCastExpr, + TypeTy *TypeOfCast, + TypeTy *&CastTy, + SourceLocation &RParenLoc); + + OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, + TypeTy *&CastTy, + SourceLocation LParenLoc, + SourceLocation &RParenLoc); + + OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + OwningExprResult ParseStringLiteralExpression(); + + //===--------------------------------------------------------------------===// + // C++ Expressions + OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); + + bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, + TypeTy *ObjectType, + bool EnteringContext, + bool *MayBePseudoDestructor = 0); + + //===--------------------------------------------------------------------===// + // C++ 5.2p1: C++ Casts + OwningExprResult ParseCXXCasts(); + + //===--------------------------------------------------------------------===// + // C++ 5.2p1: C++ Type Identification + OwningExprResult ParseCXXTypeid(); + + //===--------------------------------------------------------------------===// + // C++ 5.2.4: C++ Pseudo-Destructor Expressions + OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + Action::TypeTy *ObjectType); + + //===--------------------------------------------------------------------===// + // C++ 9.3.2: C++ 'this' pointer + OwningExprResult ParseCXXThis(); + + //===--------------------------------------------------------------------===// + // C++ 15: C++ Throw Expression + OwningExprResult ParseThrowExpression(); + // EndLoc is filled with the location of the last token of the specification. + bool ParseExceptionSpecification(SourceLocation &EndLoc, + llvm::SmallVector<TypeTy*, 2> &Exceptions, + llvm::SmallVector<SourceRange, 2> &Ranges, + bool &hasAnyExceptionSpec); + + //===--------------------------------------------------------------------===// + // C++ 2.13.5: C++ Boolean Literals + OwningExprResult ParseCXXBoolLiteral(); + + //===--------------------------------------------------------------------===// + // C++ 5.2.3: Explicit type conversion (functional notation) + OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); + + bool isCXXSimpleTypeSpecifier() const; + + /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. + /// This should only be called when the current token is known to be part of + /// simple-type-specifier. + void ParseCXXSimpleTypeSpecifier(DeclSpec &DS); + + bool ParseCXXTypeSpecifierSeq(DeclSpec &DS); + + //===--------------------------------------------------------------------===// + // C++ 5.3.4 and 5.3.5: C++ new and delete + bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D); + void ParseDirectNewDeclarator(Declarator &D); + OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); + OwningExprResult ParseCXXDeleteExpression(bool UseGlobal, + SourceLocation Start); + + //===--------------------------------------------------------------------===// + // C++ if/switch/while condition expression. + bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult, + SourceLocation Loc, bool ConvertToBoolean); + + //===--------------------------------------------------------------------===// + // C++ types + + //===--------------------------------------------------------------------===// + // C99 6.7.8: Initialization. + + /// ParseInitializer + /// initializer: [C99 6.7.8] + /// assignment-expression + /// '{' ... + OwningExprResult ParseInitializer() { + if (Tok.isNot(tok::l_brace)) + return ParseAssignmentExpression(); + return ParseBraceInitializer(); + } + OwningExprResult ParseBraceInitializer(); + OwningExprResult ParseInitializerWithPotentialDesignator(); + + //===--------------------------------------------------------------------===// + // clang Expressions + + OwningExprResult ParseBlockLiteralExpression(); // ^{...} + + //===--------------------------------------------------------------------===// + // Objective-C Expressions + OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation); + OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc); + OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCMessageExpression(); + OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, + SourceLocation SuperLoc, + TypeTy *ReceiverType, + ExprArg ReceiverExpr); + OwningExprResult ParseAssignmentExprWithObjCMessageExprStart( + SourceLocation LBracloc, SourceLocation SuperLoc, + TypeTy *ReceiverType, ExprArg ReceiverExpr); + bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr); + + //===--------------------------------------------------------------------===// + // C99 6.8: Statements and Blocks. + + OwningStmtResult ParseStatement() { + return ParseStatementOrDeclaration(true); + } + OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); + OwningStmtResult ParseLabeledStatement(AttributeList *Attr); + OwningStmtResult ParseCaseStatement(AttributeList *Attr); + OwningStmtResult ParseDefaultStatement(AttributeList *Attr); + OwningStmtResult ParseCompoundStatement(AttributeList *Attr, + bool isStmtExpr = false); + OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); + bool ParseParenExprOrCondition(OwningExprResult &ExprResult, + DeclPtrTy &DeclResult, + SourceLocation Loc, + bool ConvertToBoolean); + OwningStmtResult ParseIfStatement(AttributeList *Attr); + OwningStmtResult ParseSwitchStatement(AttributeList *Attr); + OwningStmtResult ParseWhileStatement(AttributeList *Attr); + OwningStmtResult ParseDoStatement(AttributeList *Attr); + OwningStmtResult ParseForStatement(AttributeList *Attr); + OwningStmtResult ParseGotoStatement(AttributeList *Attr); + OwningStmtResult ParseContinueStatement(AttributeList *Attr); + OwningStmtResult ParseBreakStatement(AttributeList *Attr); + OwningStmtResult ParseReturnStatement(AttributeList *Attr); + OwningStmtResult ParseAsmStatement(bool &msAsm); + OwningStmtResult FuzzyParseMicrosoftAsmStatement(); + bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, + llvm::SmallVectorImpl<ExprTy *> &Constraints, + llvm::SmallVectorImpl<ExprTy *> &Exprs); + + //===--------------------------------------------------------------------===// + // C++ 6: Statements and Blocks + + OwningStmtResult ParseCXXTryBlock(AttributeList *Attr); + OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); + OwningStmtResult ParseCXXCatchBlock(); + + //===--------------------------------------------------------------------===// + // Objective-C Statements + + OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc); + OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc); + OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc); + OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc); + + + //===--------------------------------------------------------------------===// + // C99 6.7: Declarations. + + /// A context for parsing declaration specifiers. TODO: flesh this + /// out, there are other significant restrictions on specifiers than + /// would be best implemented in the parser. + enum DeclSpecContext { + DSC_normal, // normal context + DSC_class, // class context, enables 'friend' + DSC_top_level // top-level/namespace declaration context + }; + + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, + CXX0XAttributeList Attr); + DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, + SourceLocation &DeclEnd, + AttributeList *Attr, + bool RequireSemi); + DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, + bool AllowFunctionDefinitions, + SourceLocation *DeclEnd = 0); + DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); + DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl); + + bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS); + 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); + + void ParseSpecifierQualifierList(DeclSpec &DS); + + void ParseObjCTypeQualifierList(ObjCDeclSpec &DS); + + void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none); + void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); + void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, + DeclPtrTy TagDecl); + + struct FieldCallback { + virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0; + virtual ~FieldCallback() {} + + private: + virtual void _anchor(); + }; + struct ObjCPropertyCallback; + + void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback); + + bool isDeclarationSpecifier(); + bool isTypeSpecifierQualifier(); + bool isTypeQualifier() const; + + /// isKnownToBeTypeSpecifier - Return true if we know that the specified token + /// is definitely a type-specifier. Return false if it isn't part of a type + /// specifier or if we're not sure. + bool isKnownToBeTypeSpecifier(const Token &Tok) const; + + /// isDeclarationStatement - Disambiguates between a declaration or an + /// expression statement, when parsing function bodies. + /// Returns true for declaration, false for expression. + bool isDeclarationStatement() { + if (getLang().CPlusPlus) + return isCXXDeclarationStatement(); + return isDeclarationSpecifier(); + } + + /// isSimpleDeclaration - Disambiguates between a declaration or an + /// expression, mainly used for 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(); + return isDeclarationSpecifier(); + } + + /// \brief Starting with a scope specifier, identifier, or + /// template-id that refers to the current class, determine whether + /// this is a constructor declarator. + bool isConstructorDeclarator(); + + /// \brief Specifies the context in which type-id/expression + /// disambiguation will occur. + enum TentativeCXXTypeIdContext { + TypeIdInParens, + TypeIdAsTemplateArgument + }; + + + /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know + /// 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) + return isCXXTypeId(TypeIdInParens, isAmbiguous); + isAmbiguous = false; + return isTypeSpecifierQualifier(); + } + bool isTypeIdInParens() { + bool isAmbiguous; + return isTypeIdInParens(isAmbiguous); + } + + /// isCXXDeclarationStatement - C++-specialized function that disambiguates + /// between a declaration or an expression statement, when parsing function + /// bodies. Returns true for declaration, false for expression. + bool isCXXDeclarationStatement(); + + /// isCXXSimpleDeclaration - C++-specialized function that disambiguates + /// between a simple-declaration or an expression-statement. + /// 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(); + + /// isCXXFunctionDeclarator - Disambiguates between a function declarator or + /// a constructor-style initializer, when parsing declaration statements. + /// Returns true for function declarator and false for constructor-style + /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to + /// indicate that the parens were disambiguated as function declarator. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + bool isCXXFunctionDeclarator(bool warnIfAmbiguous); + + /// isCXXConditionDeclaration - Disambiguates between a declaration or an + /// expression for a condition of a if/switch/while/for statement. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + bool isCXXConditionDeclaration(); + + bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous); + bool isCXXTypeId(TentativeCXXTypeIdContext Context) { + bool isAmbiguous; + return isCXXTypeId(Context, isAmbiguous); + } + + /// TPResult - Used as the result value for functions whose purpose is to + /// disambiguate C++ constructs by "tentatively parsing" them. + /// This is a class instead of a simple enum because the implicit enum-to-bool + /// conversions may cause subtle bugs. + class TPResult { + enum Result { + TPR_true, + TPR_false, + TPR_ambiguous, + TPR_error + }; + Result Res; + TPResult(Result result) : Res(result) {} + public: + static TPResult True() { return TPR_true; } + static TPResult False() { return TPR_false; } + static TPResult Ambiguous() { return TPR_ambiguous; } + static TPResult Error() { return TPR_error; } + + bool operator==(const TPResult &RHS) const { return Res == RHS.Res; } + bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; } + }; + + /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a + /// 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. + /// Doesn't consume tokens. + TPResult isCXXDeclarationSpecifier(); + + // "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 + // resolved and tentative parsing may stop. TPResult::Ambiguous() indicates + // that more tentative parsing is necessary for disambiguation. + // They all consume tokens, so backtracking should be used after calling them. + + TPResult TryParseDeclarationSpecifier(); + TPResult TryParseSimpleDeclaration(); + TPResult TryParseTypeofSpecifier(); + TPResult TryParseInitDeclaratorList(); + TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); + TPResult TryParseParameterDeclarationClause(); + TPResult TryParseFunctionDeclarator(); + TPResult TryParseBracketDeclarator(); + + TypeResult ParseTypeName(SourceRange *Range = 0); + void ParseBlockId(); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the attribute list. + CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0); + AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0); + AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0); + AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0); + void ParseTypeofSpecifier(DeclSpec &DS); + void ParseDecltypeSpecifier(DeclSpec &DS); + + OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start); + + /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to + /// enter a new C++ declarator scope and exit it when the function is + /// finished. + class DeclaratorScopeObj { + Parser &P; + CXXScopeSpec &SS; + bool EnteredScope; + bool CreatedScope; + public: + DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss) + : P(p), SS(ss), EnteredScope(false), CreatedScope(false) {} + + void EnterDeclaratorScope() { + assert(!EnteredScope && "Already entered the scope!"); + assert(SS.isSet() && "C++ scope was not set!"); + + CreatedScope = true; + P.EnterScope(0); // Not a decl scope. + + if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS)) + EnteredScope = true; + } + + ~DeclaratorScopeObj() { + if (EnteredScope) { + assert(SS.isSet() && "C++ scope was cleared ?"); + P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS); + } + if (CreatedScope) + P.ExitScope(); + } + }; + + /// ParseDeclarator - Parse and verify a newly-initialized declarator. + void ParseDeclarator(Declarator &D); + /// A function that parses a variant of direct-declarator. + typedef void (Parser::*DirectDeclParseFunction)(Declarator&); + void ParseDeclaratorInternal(Declarator &D, + DirectDeclParseFunction DirectDeclParser); + void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, + bool CXX0XAttributesAllowed = true); + void ParseDirectDeclarator(Declarator &D); + void ParseParenDeclarator(Declarator &D); + void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, + AttributeList *AttrList = 0, + bool RequiresArg = false); + void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, + IdentifierInfo *FirstIdent, + SourceLocation FirstIdentLoc, + Declarator &D); + void ParseBracketDeclarator(Declarator &D); + + //===--------------------------------------------------------------------===// + // C++ 7: Declarations [dcl.dcl] + + bool isCXX0XAttributeSpecifier(bool FullLookahead = false, + tok::TokenKind *After = 0); + + DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); + DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context); + DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, + SourceLocation &DeclEnd, + CXX0XAttributeList Attrs); + DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AttributeList *Attr); + DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); + DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd); + DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + SourceLocation &DeclEnd); + + //===--------------------------------------------------------------------===// + // C++ 9: classes [class] and C structs/unions. + TypeResult ParseClassName(SourceLocation &EndLocation, + CXXScopeSpec *SS = 0); + void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, + DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + AccessSpecifier AS = AS_none, + bool SuppressDeclarations = false); + void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, + DeclPtrTy TagDecl); + void ParseCXXClassMemberDeclaration(AccessSpecifier AS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + void ParseConstructorInitializer(DeclPtrTy ConstructorDecl); + MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl); + void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, + DeclPtrTy ThisDecl); + + //===--------------------------------------------------------------------===// + // C++ 10: Derived classes [class.derived] + void ParseBaseClause(DeclPtrTy ClassDecl); + BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl); + AccessSpecifier getAccessSpecifierIfPresent() const; + + bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Id, + bool AssumeTemplateId, + SourceLocation TemplateKWLoc); + bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, + TypeTy *ObjectType, + UnqualifiedId &Result); + bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, + bool AllowDestructorName, + bool AllowConstructorName, + TypeTy *ObjectType, + UnqualifiedId &Result); + + //===--------------------------------------------------------------------===// + // C++ 14: Templates [temp] + typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList; + + // C++ 14.1: Template Parameters [temp.param] + DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); + DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context, + SourceLocation &DeclEnd, + AccessSpecifier AS); + DeclPtrTy ParseSingleDeclarationAfterTemplate( + unsigned Context, + const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, + AccessSpecifier AS=AS_none); + bool ParseTemplateParameters(unsigned Depth, + TemplateParameterList &TemplateParams, + SourceLocation &LAngleLoc, + SourceLocation &RAngleLoc); + bool ParseTemplateParameterList(unsigned Depth, + TemplateParameterList &TemplateParams); + bool isStartOfTemplateTypeParameter(); + DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); + // C++ 14.3: Template arguments [temp.arg] + typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList; + + bool ParseTemplateIdAfterTemplateName(TemplateTy Template, + SourceLocation TemplateNameLoc, + const CXXScopeSpec *SS, + bool ConsumeLastToken, + SourceLocation &LAngleLoc, + TemplateArgList &TemplateArgs, + SourceLocation &RAngleLoc); + + bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, + const CXXScopeSpec *SS, + UnqualifiedId &TemplateName, + SourceLocation TemplateKWLoc = SourceLocation(), + bool AllowTypeAnnotation = true); + void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + bool IsTemplateArgumentList(unsigned Skip = 0); + bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); + ParsedTemplateArgument ParseTemplateTemplateArgument(); + ParsedTemplateArgument ParseTemplateArgument(); + DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, + SourceLocation TemplateLoc, + SourceLocation &DeclEnd); + + //===--------------------------------------------------------------------===// + // GNU G++: Type Traits [Type-Traits.html in the GCC manual] + OwningExprResult ParseUnaryTypeTrait(); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Scope.h b/contrib/llvm/tools/clang/include/clang/Parse/Scope.h new file mode 100644 index 0000000..023f40d --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Scope.h @@ -0,0 +1,329 @@ +//===--- Scope.h - Scope interface ------------------------------*- 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 Scope interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_SCOPE_H +#define LLVM_CLANG_PARSE_SCOPE_H + +#include "clang/Parse/Action.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace clang { + +/// Scope - A scope is a transient data structure that is used while parsing the +/// program. It assists with resolving identifiers to the appropriate +/// declaration. +/// +class Scope { +public: + /// ScopeFlags - These are bitfields that are or'd together when creating a + /// scope, which defines the sorts of things the scope contains. + enum ScopeFlags { + /// FnScope - This indicates that the scope corresponds to a function, which + /// means that labels are set here. + FnScope = 0x01, + + /// BreakScope - This is a while,do,switch,for, etc that can have break + /// stmts embedded into it. + BreakScope = 0x02, + + /// ContinueScope - This is a while,do,for, which can have continue + /// stmt embedded into it. + ContinueScope = 0x04, + + /// DeclScope - This is a scope that can contain a declaration. Some scopes + /// just contain loop constructs but don't contain decls. + DeclScope = 0x08, + + /// ControlScope - The controlling scope in a if/switch/while/for statement. + ControlScope = 0x10, + + /// ClassScope - The scope of a struct/union/class definition. + ClassScope = 0x20, + + /// BlockScope - This is a scope that corresponds to a block 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. + BlockScope = 0x40, + + /// TemplateParamScope - This is a scope that corresponds to the + /// template parameters of a C++ template. Template parameter + /// scope starts at the 'template' keyword and ends when the + /// template declaration ends. + TemplateParamScope = 0x80, + + /// FunctionPrototypeScope - This is a scope that corresponds to the + /// parameters within a function prototype. + FunctionPrototypeScope = 0x100, + + /// AtCatchScope - This is a scope that corresponds to the Objective-C + /// @catch statement. + AtCatchScope = 0x200, + + /// ObjCMethodScope - This scope corresponds to an Objective-C method body. + /// It always has FnScope and DeclScope set as well. + ObjCMethodScope = 0x400, + + /// ElseScope - This scope corresponds to an 'else' scope of an if/then/else + /// statement. + ElseScope = 0x800 + }; +private: + /// The parent scope for this scope. This is null for the translation-unit + /// scope. + Scope *AnyParent; + + /// Depth - This is the depth of this scope. The translation-unit scope has + /// depth 0. + unsigned short Depth; + + /// Flags - This contains a set of ScopeFlags, which indicates how the scope + /// interrelates with other control flow statements. + unsigned short Flags; + + /// FnParent - If this scope has a parent scope that is a function body, this + /// 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 + /// preceeding BreakParent/ContinueParent if this scope is not one, or null if + /// there is no containing break/continue scope. + Scope *BreakParent, *ContinueParent; + + /// ControlParent - This is a direct link to the immediately + /// preceeding 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; + + /// TemplateParamParent - This is a direct link to the + /// immediately containing template parameter scope. In the + /// case of nested templates, template parameter scopes can have + /// other template parameter scopes as parents. + Scope *TemplateParamParent; + + /// DeclsInScope - This keeps track of all declarations in this scope. When + /// the declaration is added to the scope, it is set as the current + /// declaration for the identifier in the IdentifierTable. When the scope is + /// popped, these declarations are removed from the IdentifierTable's notion + /// of current declaration. It is up to the current Action implementation to + /// implement these semantics. + typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy; + DeclSetTy DeclsInScope; + + /// Entity - The entity with which this scope is associated. For + /// example, the entity of a class scope is the class itself, the + /// entity of a function scope is a function, etc. This field is + /// maintained by the Action implementation. + void *Entity; + + typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy; + UsingDirectivesTy UsingDirectives; + + /// \brief The number of errors at the start of the given scope. + unsigned NumErrorsAtStart; + +public: + Scope(Scope *Parent, unsigned ScopeFlags) { + Init(Parent, ScopeFlags); + } + + /// getFlags - Return the flags for this scope. + /// + unsigned getFlags() const { return Flags; } + void setFlags(unsigned F) { Flags = F; } + + /// isBlockScope - Return true if this scope does not correspond to a + /// closure. + bool isBlockScope() const { return Flags & BlockScope; } + + /// getParent - Return the scope that this is nested in. + /// + const Scope *getParent() const { return AnyParent; } + Scope *getParent() { return AnyParent; } + + /// getFnParent - Return the closest scope that is a function body. + /// + const Scope *getFnParent() const { return FnParent; } + 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. + Scope *getContinueParent() { + if (ContinueParent && !ContinueParent->isBlockScope()) + return ContinueParent; + return 0; + } + + const Scope *getContinueParent() const { + return const_cast<Scope*>(this)->getContinueParent(); + } + + /// 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. + Scope *getBreakParent() { + if (BreakParent && !BreakParent->isBlockScope()) + return BreakParent; + return 0; + } + 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; } + + Scope *getTemplateParamParent() { return TemplateParamParent; } + const Scope *getTemplateParamParent() const { return TemplateParamParent; } + + typedef DeclSetTy::iterator decl_iterator; + decl_iterator decl_begin() const { return DeclsInScope.begin(); } + decl_iterator decl_end() const { return DeclsInScope.end(); } + bool decl_empty() const { return DeclsInScope.empty(); } + + void AddDecl(Action::DeclPtrTy D) { + DeclsInScope.insert(D); + } + + void RemoveDecl(Action::DeclPtrTy D) { + DeclsInScope.erase(D); + } + + /// isDeclScope - Return true if this is the scope that the specified decl is + /// declared in. + bool isDeclScope(Action::DeclPtrTy D) { + return DeclsInScope.count(D) != 0; + } + + void* getEntity() const { return Entity; } + void setEntity(void *E) { Entity = E; } + + /// \brief Retrieve the number of errors that had been emitted when we + /// entered this scope. + unsigned getNumErrorsAtStart() const { return NumErrorsAtStart; } + + void setNumErrorsAtStart(unsigned NumErrors) { + NumErrorsAtStart = NumErrors; + } + + /// isClassScope - Return true if this scope is a class/struct/union scope. + bool isClassScope() const { + return (getFlags() & Scope::ClassScope); + } + + /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline + /// method scope or is inside one. + bool isInCXXInlineMethodScope() const { + if (const Scope *FnS = getFnParent()) { + assert(FnS->getParent() && "TUScope not created?"); + return FnS->getParent()->isClassScope(); + } + return false; + } + + /// isInObjcMethodScope - Return true if this scope is, or is contained in, an + /// Objective-C method body. Note that this method is not constant time. + bool isInObjcMethodScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + // If this scope is an objc method scope, then we succeed. + if (S->getFlags() & ObjCMethodScope) + return true; + } + return false; + } + + /// isTemplateParamScope - Return true if this scope is a C++ + /// template parameter scope. + bool isTemplateParamScope() const { + return getFlags() & Scope::TemplateParamScope; + } + + /// isFunctionPrototypeScope - Return true if this scope is a + /// function prototype scope. + bool isFunctionPrototypeScope() const { + return getFlags() & Scope::FunctionPrototypeScope; + } + + /// isAtCatchScope - Return true if this scope is @catch. + bool isAtCatchScope() const { + return getFlags() & Scope::AtCatchScope; + } + + typedef UsingDirectivesTy::iterator udir_iterator; + typedef UsingDirectivesTy::const_iterator const_udir_iterator; + + void PushUsingDirective(Action::DeclPtrTy UDir) { + UsingDirectives.push_back(UDir); + } + + udir_iterator using_directives_begin() { + return UsingDirectives.begin(); + } + + udir_iterator using_directives_end() { + return UsingDirectives.end(); + } + + const_udir_iterator using_directives_begin() const { + return UsingDirectives.begin(); + } + + const_udir_iterator using_directives_end() const { + return UsingDirectives.end(); + } + + /// Init - This is used by the parser to implement scope caching. + /// + void Init(Scope *Parent, unsigned ScopeFlags) { + AnyParent = Parent; + Depth = AnyParent ? AnyParent->Depth+1 : 0; + Flags = ScopeFlags; + + if (AnyParent) { + FnParent = AnyParent->FnParent; + BreakParent = AnyParent->BreakParent; + ContinueParent = AnyParent->ContinueParent; + ControlParent = AnyParent->ControlParent; + BlockParent = AnyParent->BlockParent; + TemplateParamParent = AnyParent->TemplateParamParent; + } else { + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 0; + TemplateParamParent = 0; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (Flags & FnScope) FnParent = this; + if (Flags & BreakScope) BreakParent = this; + if (Flags & ContinueScope) ContinueParent = this; + if (Flags & ControlScope) ControlParent = this; + if (Flags & BlockScope) BlockParent = this; + if (Flags & TemplateParamScope) TemplateParamParent = this; + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + NumErrorsAtStart = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Template.h b/contrib/llvm/tools/clang/include/clang/Parse/Template.h new file mode 100644 index 0000000..1f8ccfb --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Parse/Template.h @@ -0,0 +1,183 @@ +//===--- Template.h - Template Parsing Data Types -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides data structures that store the parsed representation of +// templates. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_PARSE_TEMPLATE_H +#define LLVM_CLANG_PARSE_TEMPLATE_H + +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Ownership.h" +#include <cassert> + +namespace clang { + /// \brief Represents the parsed form of a C++ template argument. + class ParsedTemplateArgument { + public: + /// \brief Describes the kind of template argument that was parsed. + enum KindType { + /// \brief A template type parameter, stored as a type. + Type, + /// \brief A non-type template parameter, stored as an expression. + NonType, + /// \brief A template template argument, stored as a template name. + Template + }; + + /// \brief Build an empty template argument. This template argument + ParsedTemplateArgument() : Kind(Type), Arg(0) { } + + /// \brief Create a template type argument or non-type template argument. + /// + /// \param Arg the template type argument or non-type template argument. + /// \param Loc the location of the type. + ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) + : Kind(Kind), Arg(Arg), Loc(Loc) { } + + /// \brief Create a template template argument. + /// + /// \param SS the C++ scope specifier that precedes the template name, if + /// any. + /// + /// \param Template the template to which this template template + /// argument refers. + /// + /// \param TemplateLoc the location of the template name. + ParsedTemplateArgument(const CXXScopeSpec &SS, + ActionBase::TemplateTy Template, + SourceLocation TemplateLoc) + : Kind(ParsedTemplateArgument::Template), Arg(Template.get()), + Loc(TemplateLoc), SS(SS) { } + + /// \brief Determine whether the given template argument is invalid. + bool isInvalid() { return Arg == 0; } + + /// \brief Determine what kind of template argument we have. + KindType getKind() const { return Kind; } + + /// \brief Retrieve the template type argument's type. + ActionBase::TypeTy *getAsType() const { + assert(Kind == Type && "Not a template type argument"); + return Arg; + } + + /// \brief Retrieve the non-type template argument's expression. + ActionBase::ExprTy *getAsExpr() const { + assert(Kind == NonType && "Not a non-type template argument"); + return Arg; + } + + /// \brief Retrieve the template template argument's template name. + ActionBase::TemplateTy getAsTemplate() const { + assert(Kind == Template && "Not a template template argument"); + return ActionBase::TemplateTy::make(Arg); + } + + /// \brief Retrieve the location of the template argument. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the nested-name-specifier that precedes the template + /// name in a template template argument. + const CXXScopeSpec &getScopeSpec() const { + assert(Kind == Template && + "Only template template arguments can have a scope specifier"); + return SS; + } + + private: + KindType Kind; + + /// \brief The actual template argument representation, which may be + /// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an + /// expression), or an ActionBase::TemplateTy (for a template). + void *Arg; + + /// \brief the location of the template argument. + SourceLocation Loc; + + /// \brief The nested-name-specifier that can accompany a template template + /// argument. + CXXScopeSpec SS; + }; + + /// \brief Information about a template-id annotation + /// token. + /// + /// A template-id annotation token contains the template declaration, + /// template arguments, whether those template arguments were types, + /// expressions, or template names, and the source locations for important + /// tokens. All of the information about template arguments is allocated + /// directly after this structure. + struct TemplateIdAnnotation { + /// TemplateNameLoc - The location of the template name within the + /// source. + SourceLocation TemplateNameLoc; + + /// FIXME: Temporarily stores the name of a specialization + IdentifierInfo *Name; + + /// FIXME: Temporarily stores the overloaded operator kind. + OverloadedOperatorKind Operator; + + /// The declaration of the template corresponding to the + /// template-name. This is an Action::TemplateTy. + void *Template; + + /// The kind of template that Template refers to. + TemplateNameKind Kind; + + /// The location of the '<' before the template argument + /// list. + SourceLocation LAngleLoc; + + /// The location of the '>' after the template argument + /// list. + SourceLocation RAngleLoc; + + /// NumArgs - The number of template arguments. + unsigned NumArgs; + + /// \brief Retrieves a pointer to the template arguments + ParsedTemplateArgument *getTemplateArgs() { + return reinterpret_cast<ParsedTemplateArgument *>(this + 1); + } + + static TemplateIdAnnotation* Allocate(unsigned NumArgs) { + TemplateIdAnnotation *TemplateId + = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + + sizeof(ParsedTemplateArgument) * NumArgs); + TemplateId->NumArgs = NumArgs; + return TemplateId; + } + + void Destroy() { free(this); } + }; + +#if !defined(DISABLE_SMART_POINTERS) + inline void ASTTemplateArgsPtr::destroy() { + if (!Count) + return; + + for (unsigned I = 0; I != Count; ++I) + if (Args[I].getKind() == ParsedTemplateArgument::NonType) + Actions.DeleteExpr(Args[I].getAsExpr()); + + Count = 0; + } +#endif + + inline const ParsedTemplateArgument & + ASTTemplateArgsPtr::operator[](unsigned Arg) const { + return Args[Arg]; + } +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h b/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h new file mode 100644 index 0000000..f32906a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h @@ -0,0 +1,48 @@ +//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- 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 DeltaTree class. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_REWRITE_DELTATREE_H +#define CLANG_REWRITE_DELTATREE_H + +namespace clang { + + /// DeltaTree - a multiway search tree (BTree) structure with some fancy + /// features. B-Trees are generally more memory and cache efficient than + /// binary trees, because they store multiple keys/values in each node. This + /// implements a key/value mapping from index to delta, and allows fast lookup + /// on index. However, an added (important) bonus is that it can also + /// efficiently tell us the full accumulated delta for a specific file offset + /// as well, without traversing the whole tree. + class DeltaTree { + void *Root; // "DeltaTreeNode *" + void operator=(const DeltaTree&); // DO NOT IMPLEMENT + public: + DeltaTree(); + + // Note: Currently we only support copying when the RHS is empty. + DeltaTree(const DeltaTree &RHS); + ~DeltaTree(); + + /// getDeltaAt - Return the accumulated delta at the specified file offset. + /// This includes all insertions or delections that occurred *before* the + /// specified file index. + int getDeltaAt(unsigned FileIndex) const; + + /// AddDelta - When a change is made that shifts around the text buffer, + /// this method is used to record that info. It inserts a delta of 'Delta' + /// into the current DeltaTree at offset FileIndex. + void AddDelta(unsigned FileIndex, int Delta); + }; +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h b/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h new file mode 100644 index 0000000..88caf85 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h @@ -0,0 +1,81 @@ +//==- HTMLRewrite.h - Translate source code into prettified HTML ---*- 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 set of functions used for translating source code +// into beautified HTML. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_HTMLREWRITER_H +#define LLVM_CLANG_HTMLREWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include <string> + +namespace clang { + +class Rewriter; +class RewriteBuffer; +class Preprocessor; + +namespace html { + + /// HighlightRange - Highlight a range in the source code with the specified + /// start/end tags. B/E must be in the same file. This ensures that + /// start/end tags are placed at the start/end of each line if the range is + /// multiline. + void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, + const char *StartTag, const char *EndTag); + + /// HighlightRange - Highlight a range in the source code with the specified + /// start/end tags. The Start/end of the range must be in the same file. + /// This ensures that start/end tags are placed at the start/end of each line + /// if the range is multiline. + inline void HighlightRange(Rewriter &R, SourceRange Range, + const char *StartTag, const char *EndTag) { + HighlightRange(R, Range.getBegin(), Range.getEnd(), StartTag, EndTag); + } + + /// HighlightRange - This is the same as the above method, but takes + /// decomposed file locations. + void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E, + const char *BufferStart, + const char *StartTag, const char *EndTag); + + /// EscapeText - HTMLize a specified file so that special characters are + /// are translated so that they are not interpreted as HTML tags. + void EscapeText(Rewriter& R, FileID FID, + bool EscapeSpaces = false, bool ReplaceTabs = false); + + /// EscapeText - HTMLized the provided string so that special characters + /// in 's' are not interpreted as HTML tags. Unlike the version of + /// EscapeText that rewrites a file, this version by default replaces tabs + /// with spaces. + std::string EscapeText(const std::string& s, + bool EscapeSpaces = false, bool ReplaceTabs = false); + + void AddLineNumbers(Rewriter& R, FileID FID); + + void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID, + const char *title = NULL); + + /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with + /// information about keywords, comments, etc. + void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP); + + /// HighlightMacros - This uses the macro table state from the end of the + /// file, to reexpand macros and insert (into the HTML) information about the + /// macro expansions. This won't be perfectly perfect, but it will be + /// reasonably close. + void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP); + +} // end html namespace +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h b/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h new file mode 100644 index 0000000..c0bd741 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h @@ -0,0 +1,230 @@ +//===--- RewriteRope.h - Rope specialized for rewriter ----------*- 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 RewriteRope class, which is a powerful string class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITEROPE_H +#define LLVM_CLANG_REWRITEROPE_H + +#include <cstring> +#include <cassert> +#include <iterator> + +namespace clang { + //===--------------------------------------------------------------------===// + // RopeRefCountString Class + //===--------------------------------------------------------------------===// + + /// RopeRefCountString - This struct is allocated with 'new char[]' from the + /// heap, and represents a reference counted chunk of string data. When its + /// ref count drops to zero, it is delete[]'d. This is primarily managed + /// through the RopePiece class below. + struct RopeRefCountString { + unsigned RefCount; + char Data[1]; // Variable sized. + + void addRef() { + if (this) ++RefCount; + } + + void dropRef() { + if (this && --RefCount == 0) + delete [] (char*)this; + } + }; + + //===--------------------------------------------------------------------===// + // RopePiece Class + //===--------------------------------------------------------------------===// + + /// RopePiece - This class represents a view into a RopeRefCountString object. + /// This allows references to string data to be efficiently chopped up and + /// moved around without having to push around the string data itself. + /// + /// For example, we could have a 1M RopePiece and want to insert something + /// into the middle of it. To do this, we split it into two RopePiece objects + /// that both refer to the same underlying RopeRefCountString (just with + /// different offsets) which is a nice constant time operation. + struct RopePiece { + RopeRefCountString *StrData; + unsigned StartOffs; + unsigned EndOffs; + + RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {} + + RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) + : StrData(Str), StartOffs(Start), EndOffs(End) { + StrData->addRef(); + } + RopePiece(const RopePiece &RP) + : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) { + StrData->addRef(); + } + + ~RopePiece() { + StrData->dropRef(); + } + + void operator=(const RopePiece &RHS) { + if (StrData != RHS.StrData) { + StrData->dropRef(); + StrData = RHS.StrData; + StrData->addRef(); + } + StartOffs = RHS.StartOffs; + EndOffs = RHS.EndOffs; + } + + const char &operator[](unsigned Offset) const { + return StrData->Data[Offset+StartOffs]; + } + char &operator[](unsigned Offset) { + return StrData->Data[Offset+StartOffs]; + } + + unsigned size() const { return EndOffs-StartOffs; } + }; + + //===--------------------------------------------------------------------===// + // RopePieceBTreeIterator Class + //===--------------------------------------------------------------------===// + + /// RopePieceBTreeIterator - This class provides read-only forward iteration + /// over bytes that are in a RopePieceBTree. This first iterates over bytes + /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf, + /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree. + class RopePieceBTreeIterator : + public std::iterator<std::forward_iterator_tag, const char, ptrdiff_t> { + /// CurNode - The current B+Tree node that we are inspecting. + const void /*RopePieceBTreeLeaf*/ *CurNode; + /// CurPiece - The current RopePiece in the B+Tree node that we're + /// inspecting. + const RopePiece *CurPiece; + /// CurChar - The current byte in the RopePiece we are pointing to. + unsigned CurChar; + public: + // begin iterator. + RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); + // end iterator + RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {} + + char operator*() const { + return (*CurPiece)[CurChar]; + } + + bool operator==(const RopePieceBTreeIterator &RHS) const { + return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar; + } + bool operator!=(const RopePieceBTreeIterator &RHS) const { + return !operator==(RHS); + } + + RopePieceBTreeIterator& operator++() { // Preincrement + if (CurChar+1 < CurPiece->size()) + ++CurChar; + else + MoveToNextPiece(); + return *this; + } + inline RopePieceBTreeIterator operator++(int) { // Postincrement + RopePieceBTreeIterator tmp = *this; ++*this; return tmp; + } + private: + void MoveToNextPiece(); + }; + + //===--------------------------------------------------------------------===// + // RopePieceBTree Class + //===--------------------------------------------------------------------===// + + class RopePieceBTree { + void /*RopePieceBTreeNode*/ *Root; + void operator=(const RopePieceBTree &); // DO NOT IMPLEMENT + public: + RopePieceBTree(); + RopePieceBTree(const RopePieceBTree &RHS); + ~RopePieceBTree(); + + typedef RopePieceBTreeIterator iterator; + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + unsigned size() const; + unsigned empty() const { return size() == 0; } + + void clear(); + + void insert(unsigned Offset, const RopePiece &R); + + void erase(unsigned Offset, unsigned NumBytes); + }; + + //===--------------------------------------------------------------------===// + // RewriteRope Class + //===--------------------------------------------------------------------===// + +/// RewriteRope - A powerful string class. This class supports extremely +/// efficient insertions and deletions into the middle of it, even for +/// ridiculously long strings. +class RewriteRope { + RopePieceBTree Chunks; + + /// We allocate space for string data out of a buffer of size AllocChunkSize. + /// This keeps track of how much space is left. + RopeRefCountString *AllocBuffer; + unsigned AllocOffs; + enum { AllocChunkSize = 4080 }; + +public: + RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {} + RewriteRope(const RewriteRope &RHS) + : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) { + } + + ~RewriteRope() { + // If we had an allocation buffer, drop our reference to it. + AllocBuffer->dropRef(); + } + + typedef RopePieceBTree::iterator iterator; + typedef RopePieceBTree::iterator const_iterator; + iterator begin() const { return Chunks.begin(); } + iterator end() const { return Chunks.end(); } + unsigned size() const { return Chunks.size(); } + + void clear() { + Chunks.clear(); + } + + void assign(const char *Start, const char *End) { + clear(); + if (Start != End) + Chunks.insert(0, MakeRopeString(Start, End)); + } + + void insert(unsigned Offset, const char *Start, const char *End) { + assert(Offset <= size() && "Invalid position to insert!"); + if (Start == End) return; + Chunks.insert(Offset, MakeRopeString(Start, End)); + } + + void erase(unsigned Offset, unsigned NumBytes) { + assert(Offset+NumBytes <= size() && "Invalid region to erase!"); + if (NumBytes == 0) return; + Chunks.erase(Offset, NumBytes); + } + +private: + RopePiece MakeRopeString(const char *Start, const char *End); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h new file mode 100644 index 0000000..adda866 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h @@ -0,0 +1,225 @@ +//===--- Rewriter.h - Code rewriting interface ------------------*- 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 Rewriter class, which is used for code +// transformations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITER_H +#define LLVM_CLANG_REWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Rewrite/DeltaTree.h" +#include "clang/Rewrite/RewriteRope.h" +#include "llvm/ADT/StringRef.h" +#include <cstring> +#include <map> +#include <string> +#include <vector> + +namespace llvm { class raw_ostream; } + +namespace clang { + class LangOptions; + class Rewriter; + class SourceManager; + class Stmt; + +/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original +/// input with modifications get a new RewriteBuffer associated with them. The +/// RewriteBuffer captures the modified text itself as well as information used +/// to map between SourceLocation's in the original input and offsets in the +/// RewriteBuffer. For example, if text is inserted into the buffer, any +/// locations after the insertion point have to be mapped. +class RewriteBuffer { + friend class Rewriter; + /// Deltas - Keep track of all the deltas in the source code due to insertions + /// and deletions. + DeltaTree Deltas; + + /// Buffer - This is the actual buffer itself. Note that using a vector or + /// string is a horribly inefficient way to do this, we should use a rope + /// instead. + typedef RewriteRope BufferTy; + BufferTy Buffer; +public: + typedef BufferTy::const_iterator iterator; + iterator begin() const { return Buffer.begin(); } + iterator end() const { return Buffer.end(); } + unsigned size() const { return Buffer.size(); } + + llvm::raw_ostream &write(llvm::raw_ostream &) const; + + /// RemoveText - Remove the specified text. + void RemoveText(unsigned OrigOffset, unsigned Size); + + /// InsertText - Insert some text at the specified point, where the offset in + /// the buffer is specified relative to the original SourceBuffer. The + /// text is inserted after the specified location. + /// + void InsertText(unsigned OrigOffset, const llvm::StringRef &Str, + bool InsertAfter = true); + + + /// InsertTextBefore - Insert some text before the specified point, where the + /// offset in the buffer is specified relative to the original + /// SourceBuffer. The text is inserted before the specified location. This is + /// method is the same as InsertText with "InsertAfter == false". + void InsertTextBefore(unsigned OrigOffset, const llvm::StringRef &Str) { + InsertText(OrigOffset, Str, false); + } + + /// InsertTextAfter - Insert some text at the specified point, where the + /// offset in the buffer is specified relative to the original SourceBuffer. + /// The text is inserted after the specified location. + void InsertTextAfter(unsigned OrigOffset, const llvm::StringRef &Str) { + InsertText(OrigOffset, Str); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + void ReplaceText(unsigned OrigOffset, unsigned OrigLength, + const llvm::StringRef &NewStr); + +private: // Methods only usable by Rewriter. + + /// Initialize - Start this rewrite buffer out with a copy of the unmodified + /// input buffer. + void Initialize(const char *BufStart, const char *BufEnd) { + Buffer.assign(BufStart, BufEnd); + } + + /// getMappedOffset - Given an offset into the original SourceBuffer that this + /// RewriteBuffer is based on, map it into the offset space of the + /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a + /// position where text is inserted, the location returned will be after any + /// inserted text at the position. + unsigned getMappedOffset(unsigned OrigOffset, + bool AfterInserts = false) const{ + return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset; + } + + /// AddInsertDelta - When an insertion is made at a position, this + /// method is used to record that information. + void AddInsertDelta(unsigned OrigOffset, int Change) { + return Deltas.AddDelta(2*OrigOffset, Change); + } + + /// AddReplaceDelta - When a replacement/deletion is made at a position, this + /// method is used to record that information. + void AddReplaceDelta(unsigned OrigOffset, int Change) { + return Deltas.AddDelta(2*OrigOffset+1, Change); + } +}; + + +/// Rewriter - This is the main interface to the rewrite buffers. Its primary +/// job is to dispatch high-level requests to the low-level RewriteBuffers that +/// are involved. +class Rewriter { + SourceManager *SourceMgr; + const LangOptions *LangOpts; + std::map<FileID, RewriteBuffer> RewriteBuffers; +public: + typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator; + + explicit Rewriter(SourceManager &SM, const LangOptions &LO) + : SourceMgr(&SM), LangOpts(&LO) {} + explicit Rewriter() : SourceMgr(0), LangOpts(0) {} + + void setSourceMgr(SourceManager &SM, const LangOptions &LO) { + SourceMgr = &SM; + LangOpts = &LO; + } + SourceManager &getSourceMgr() { return *SourceMgr; } + const LangOptions &getLangOpts() { return *LangOpts; } + + /// isRewritable - Return true if this location is a raw file location, which + /// is rewritable. Locations from macros, etc are not rewritable. + static bool isRewritable(SourceLocation Loc) { + return Loc.isFileID(); + } + + /// getRangeSize - Return the size in bytes of the specified range if they + /// are in the same file. If not, this returns -1. + int getRangeSize(SourceRange Range) const; + + /// getRewrittenText - Return the rewritten form of the text in the specified + /// range. If the start or end of the range was unrewritable or if they are + /// in different buffers, this returns an empty string. + /// + /// Note that this method is not particularly efficient. + /// + std::string getRewrittenText(SourceRange Range) const; + + /// InsertText - Insert the specified string at the specified location in the + /// original buffer. This method returns true (and does nothing) if the input + /// location was not rewritable, false otherwise. + bool InsertText(SourceLocation Loc, const llvm::StringRef &Str, + bool InsertAfter = true); + + /// InsertTextAfter - Insert the specified string at the specified location in + /// the original buffer. This method returns true (and does nothing) if + /// the input location was not rewritable, false otherwise. Text is + /// inserted after any other text that has been previously inserted + /// at the some point (the default behavior for InsertText). + bool InsertTextAfter(SourceLocation Loc, const llvm::StringRef &Str) { + return InsertText(Loc, Str); + } + + /// InsertText - Insert the specified string at the specified location in the + /// original buffer. This method returns true (and does nothing) if the input + /// location was not rewritable, false otherwise. Text is + /// inserted before any other text that has been previously inserted + /// at the some point. + bool InsertTextBefore(SourceLocation Loc, const llvm::StringRef &Str) { + return InsertText(Loc, Str, false); + } + + /// RemoveText - Remove the specified text region. + bool RemoveText(SourceLocation Start, unsigned Length); + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceLocation Start, unsigned OrigLength, + const llvm::StringRef &NewStr); + + /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty + /// printer to generate the replacement code. This returns true if the input + /// could not be rewritten, or false if successful. + bool ReplaceStmt(Stmt *From, Stmt *To); + + /// getEditBuffer - This is like getRewriteBufferFor, but always returns a + /// buffer, and allows you to write on it directly. This is useful if you + /// want efficient low-level access to apis for scribbling on one specific + /// FileID's buffer. + RewriteBuffer &getEditBuffer(FileID FID); + + /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. + /// If no modification has been made to it, return null. + const RewriteBuffer *getRewriteBufferFor(FileID FID) const { + std::map<FileID, RewriteBuffer>::const_iterator I = + RewriteBuffers.find(FID); + return I == RewriteBuffers.end() ? 0 : &I->second; + } + + // Iterators over rewrite buffers. + buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } + buffer_iterator buffer_end() { return RewriteBuffers.end(); } + +private: + unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h new file mode 100644 index 0000000..62ea12a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h @@ -0,0 +1,79 @@ +//===--- TokenRewriter.h - Token-based Rewriter -----------------*- 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 TokenRewriter class, which is used for code +// transformations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOKENREWRITER_H +#define LLVM_CLANG_TOKENREWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/OwningPtr.h" +#include <list> +#include <map> + +namespace clang { + class Token; + class LangOptions; + class ScratchBuffer; + + class TokenRewriter { + /// TokenList - This is the list of raw tokens that make up this file. Each + /// of these tokens has a unique SourceLocation, which is a FileID. + std::list<Token> TokenList; + + /// TokenRefTy - This is the type used to refer to a token in the TokenList. + typedef std::list<Token>::iterator TokenRefTy; + + /// TokenAtLoc - This map indicates which token exists at a specific + /// SourceLocation. Since each token has a unique SourceLocation, this is a + /// one to one map. The token can return its own location directly, to map + /// backwards. + std::map<SourceLocation, TokenRefTy> TokenAtLoc; + + /// ScratchBuf - This is the buffer that we create scratch tokens from. + /// + llvm::OwningPtr<ScratchBuffer> ScratchBuf; + + TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT + void operator=(const TokenRewriter&); // DO NOT IMPLEMENT. + public: + /// TokenRewriter - This creates a TokenRewriter for the file with the + /// specified FileID. + TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO); + ~TokenRewriter(); + + typedef std::list<Token>::const_iterator token_iterator; + token_iterator token_begin() const { return TokenList.begin(); } + token_iterator token_end() const { return TokenList.end(); } + + + token_iterator AddTokenBefore(token_iterator I, const char *Val); + token_iterator AddTokenAfter(token_iterator I, const char *Val) { + assert(I != token_end() && "Cannot insert after token_end()!"); + return AddTokenBefore(++I, Val); + } + + private: + /// RemapIterator - Convert from token_iterator (a const iterator) to + /// TokenRefTy (a non-const iterator). + TokenRefTy RemapIterator(token_iterator I); + + /// AddToken - Add the specified token into the Rewriter before the other + /// position. + TokenRefTy AddToken(const Token &T, TokenRefTy Where); + }; + + + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h new file mode 100644 index 0000000..1f1c0cc --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -0,0 +1,555 @@ +//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- 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 CodeCompleteConsumer class. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H +#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <memory> +#include <string> + +namespace llvm { +class raw_ostream; +} + +namespace clang { + +/// \brief Default priority values for code-completion results based +/// on their kind. +enum { + /// \brief Priority for a declaration that is in the local scope. + CCP_LocalDeclaration = 8, + /// \brief Priority for a member declaration found from the current + /// method or member function. + CCP_MemberDeclaration = 20, + /// \brief Priority for a language keyword (that isn't any of the other + /// categories). + CCP_Keyword = 30, + /// \brief Priority for a code pattern. + CCP_CodePattern = 30, + /// \brief Priority for a type. + CCP_Type = 40, + /// \brief Priority for a non-type declaration. + CCP_Declaration = 50, + /// \brief Priority for a constant value (e.g., enumerator). + CCP_Constant = 60, + /// \brief Priority for a preprocessor macro. + CCP_Macro = 70, + /// \brief Priority for a nested-name-specifier. + CCP_NestedNameSpecifier = 75, + /// \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 value deltas that are applied to code-completion results +/// based on the context of the result. +enum { + /// \brief The result is in a base class. + CCD_InBaseClass = 2 +}; + +class FunctionDecl; +class FunctionType; +class FunctionTemplateDecl; +class IdentifierInfo; +class NamedDecl; +class NestedNameSpecifier; +class Sema; + +/// \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 +/// 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. +class CodeCompletionString { +public: + /// \brief The different kinds of "chunks" that can occur within a code + /// completion string. + enum ChunkKind { + /// \brief The piece of text that the user is expected to type to + /// match the code-completion string, typically a keyword or the name of a + /// declarator or macro. + CK_TypedText, + /// \brief A piece of text that should be placed in the buffer, e.g., + /// parentheses or a comma in a function call. + CK_Text, + /// \brief A code completion string that is entirely optional. For example, + /// 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 + /// call argument. + CK_Placeholder, + /// \brief A piece of text that describes something about the result but + /// should not be inserted into the buffer. + CK_Informative, + /// \brief A piece of text that describes the type of an entity or, for + /// functions and methods, the return type. + CK_ResultType, + /// \brief A piece of text that describes the parameter that corresponds + /// to the code-completion location within a function call, message send, + /// macro invocation, etc. + CK_CurrentParameter, + /// \brief A left parenthesis ('('). + CK_LeftParen, + /// \brief A right parenthesis (')'). + CK_RightParen, + /// \brief A left bracket ('['). + CK_LeftBracket, + /// \brief A right bracket (']'). + CK_RightBracket, + /// \brief A left brace ('{'). + CK_LeftBrace, + /// \brief A right brace ('}'). + CK_RightBrace, + /// \brief A left angle bracket ('<'). + CK_LeftAngle, + /// \brief A right angle bracket ('>'). + CK_RightAngle, + /// \brief A comma separator (','). + CK_Comma, + /// \brief A colon (':'). + CK_Colon, + /// \brief A semicolon (';'). + CK_SemiColon, + /// \brief An '=' sign. + CK_Equal, + /// \brief Horizontal whitespace (' '). + CK_HorizontalSpace, + /// \brief Verticle whitespace ('\n' or '\r\n', depending on the + /// 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 + /// 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 + /// (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, llvm::StringRef Text = ""); + + /// \brief Create a new text chunk. + static Chunk CreateText(llvm::StringRef Text); + + /// \brief Create a new optional chunk. + static Chunk CreateOptional(std::auto_ptr<CodeCompletionString> Optional); + + /// \brief Create a new placeholder chunk. + static Chunk CreatePlaceholder(llvm::StringRef Placeholder); + + /// \brief Create a new informative chunk. + static Chunk CreateInformative(llvm::StringRef Informative); + + /// \brief Create a new result type chunk. + static Chunk CreateResultType(llvm::StringRef ResultType); + + /// \brief Create a new current-parameter chunk. + static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter); + + /// \brief Clone the given chunk. + Chunk Clone() const; + + /// \brief Destroy this chunk, deallocating any memory it owns. + void Destroy(); + }; + +private: + /// \brief The chunks stored in this string. + llvm::SmallVector<Chunk, 4> Chunks; + + CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT + CodeCompletionString &operator=(const CodeCompletionString &); // DITTO + +public: + CodeCompletionString() { } + ~CodeCompletionString() { clear(); } + + typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator; + iterator begin() const { return Chunks.begin(); } + iterator end() const { return Chunks.end(); } + bool empty() const { return Chunks.empty(); } + unsigned size() const { return Chunks.size(); } + void clear(); + + Chunk &operator[](unsigned I) { + assert(I < size() && "Chunk index out-of-range"); + return Chunks[I]; + } + + const Chunk &operator[](unsigned I) const { + assert(I < size() && "Chunk index out-of-range"); + return Chunks[I]; + } + + /// \brief Add a new typed-text chunk. + /// The text string will be copied. + void AddTypedTextChunk(llvm::StringRef Text) { + Chunks.push_back(Chunk(CK_TypedText, Text)); + } + + /// \brief Add a new text chunk. + /// The text string will be copied. + void AddTextChunk(llvm::StringRef Text) { + Chunks.push_back(Chunk::CreateText(Text)); + } + + /// \brief Add a new optional chunk. + void AddOptionalChunk(std::auto_ptr<CodeCompletionString> Optional) { + Chunks.push_back(Chunk::CreateOptional(Optional)); + } + + /// \brief Add a new placeholder chunk. + /// The placeholder text will be copied. + void AddPlaceholderChunk(llvm::StringRef Placeholder) { + Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); + } + + /// \brief Add a new informative chunk. + /// The text will be copied. + void AddInformativeChunk(llvm::StringRef Text) { + Chunks.push_back(Chunk::CreateInformative(Text)); + } + + /// \brief Add a new result-type chunk. + /// The text will be copied. + void AddResultTypeChunk(llvm::StringRef ResultType) { + Chunks.push_back(Chunk::CreateResultType(ResultType)); + } + + /// \brief Add a new current-parameter chunk. + /// The text will be copied. + void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) { + Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); + } + + /// \brief Add a new chunk. + void AddChunk(Chunk C) { Chunks.push_back(C); } + + /// \brief Returns the text in the TypedText chunk. + const char *getTypedText() const; + + /// \brief Retrieve a string representation of the code completion string, + /// which is mainly useful for debugging. + std::string getAsString() const; + + /// \brief Clone this code-completion string. + CodeCompletionString *Clone() const; + + /// \brief Serialize this code-completion string to the given stream. + void Serialize(llvm::raw_ostream &OS) const; + + /// \brief Deserialize a code-completion string from the given string. + /// + /// \returns true if successful, false otherwise. + bool Deserialize(const char *&Str, const char *StrEnd); +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const CodeCompletionString &CCS); + +/// \brief Abstract interface for a consumer of code-completion +/// information. +class CodeCompleteConsumer { +protected: + /// \brief Whether to include macros in the code-completion results. + bool IncludeMacros; + + /// \brief Whether to include code patterns (such as for loops) within + /// the completion results. + bool IncludeCodePatterns; + + /// \brief Whether the output format for the code-completion consumer is + /// binary. + bool OutputIsBinary; + +public: + /// \brief Captures a result of code completion. + struct Result { + /// \brief Describes the kind of result generated. + enum ResultKind { + RK_Declaration = 0, //< Refers to a declaration + RK_Keyword, //< Refers to a keyword or symbol. + RK_Macro, //< Refers to a macro + RK_Pattern //< Refers to a precomputed pattern. + }; + + /// \brief The kind of result stored here. + ResultKind Kind; + + union { + /// \brief When Kind == RK_Declaration, the declaration we are referring + /// to. + NamedDecl *Declaration; + + /// \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; + }; + + /// \brief The priority of this particular code-completion result. + unsigned Priority; + + /// \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 + /// nested-name-specifier and, therefore, should be followed by '::'. + bool StartsNestedNameSpecifier : 1; + + /// \brief Whether all parameters (of a function, Objective-C + /// method, etc.) should be considered "informative". + bool AllParametersAreInformative : 1; + + /// \brief If the result should have a nested-name-specifier, this is it. + /// When \c QualifierIsInformative, the nested-name-specifier is + /// informative rather than required. + NestedNameSpecifier *Qualifier; + + /// \brief Build a result that refers to a declaration. + Result(NamedDecl *Declaration, + NestedNameSpecifier *Qualifier = 0, + bool QualifierIsInformative = false) + : Kind(RK_Declaration), Declaration(Declaration), + Priority(getPriorityFromDecl(Declaration)), StartParameter(0), + Hidden(false), QualifierIsInformative(QualifierIsInformative), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(Qualifier) { + } + + /// \brief Build a result that refers to a keyword or symbol. + Result(const char *Keyword, unsigned Priority = CCP_Keyword) + : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), + StartParameter(0), Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(0) { } + + /// \brief Build a result that refers to a macro. + Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) + : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(0) { } + + /// \brief Build a result that refers to a pattern. + Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern) + : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), + StartParameter(0), Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(0) { } + + /// \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. + CodeCompletionString *CreateCodeCompletionString(Sema &S); + + void Destroy(); + + /// brief Determine a base priority for the given declaration. + static unsigned getPriorityFromDecl(NamedDecl *ND); + }; + + class OverloadCandidate { + public: + /// \brief Describes the type of overload candidate. + enum CandidateKind { + /// \brief The candidate is a function declaration. + CK_Function, + /// \brief The candidate is a function template. + CK_FunctionTemplate, + /// \brief The "candidate" is actually a variable, expression, or block + /// 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 + /// 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) { } + + OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) + : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplate) { } + + OverloadCandidate(const FunctionType *Type) + : Kind(CK_FunctionType), Type(Type) { } + + /// \brief Determine the kind of overload candidate. + CandidateKind getKind() const { return Kind; } + + /// \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, + Sema &S) const; + }; + + CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { } + + CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + bool OutputIsBinary) + : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), + 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 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, Result *Results, + unsigned NumResults) { } + + /// \param S the semantic-analyzer object for which code-completion is being + /// done. + /// + /// \param CurrentArg the index of the current argument. + /// + /// \param Candidates an array of overload candidates. + /// + /// \param NumCandidates the number of overload candidates + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates) { } + //@} +}; + +/// \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. + llvm::raw_ostream &OS; + +public: + /// \brief Create a new printing code-completion consumer that prints its + /// results to the given raw output stream. + PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {} + + /// \brief Prints the finalized code-completion results. + virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + unsigned NumResults); + + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates); +}; + +/// \brief A code-completion consumer that prints the results it receives +/// in a format that is parsable by the CIndex library. +class CIndexCodeCompleteConsumer : public CodeCompleteConsumer { + /// \brief The raw output stream. + llvm::raw_ostream &OS; + +public: + /// \brief Create a new CIndex code-completion consumer that prints its + /// results to the given raw output stream in a format readable to the CIndex + /// library. + CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {} + + /// \brief Prints the finalized code-completion results. + virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + unsigned NumResults); + + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h new file mode 100644 index 0000000..d27e292 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h @@ -0,0 +1,59 @@ +//===--- ExternalSemaSource.h - External Sema Interface ---------*- 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 ExternalSemaSource interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H +#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H + +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExternalASTSource.h" + +namespace clang { + +class Sema; + +/// \brief An abstract interface that should be implemented by +/// external AST sources that also provide information for semantic +/// analysis. +class ExternalSemaSource : public ExternalASTSource { +public: + ExternalSemaSource() { + ExternalASTSource::SemaSource = true; + } + + /// \brief Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S) {} + + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() {} + + /// \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) { + return std::pair<ObjCMethodList, ObjCMethodList>(); + } + + // isa/cast/dyn_cast support + static bool classof(const ExternalASTSource *Source) { + return Source->SemaSource; + } + static bool classof(const ExternalSemaSource *) { return true; } +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Sema/ParseAST.h new file mode 100644 index 0000000..f6cff2a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/ParseAST.h @@ -0,0 +1,43 @@ +//===--- ParseAST.h - Define the ParseAST method ----------------*- 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 clang::ParseAST method. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_PARSEAST_H +#define LLVM_CLANG_SEMA_PARSEAST_H + +namespace clang { + class Preprocessor; + class ASTConsumer; + class ASTContext; + class CodeCompleteConsumer; + class Sema; + + /// \brief Parse the entire file specified, notifying the ASTConsumer as + /// the file is parsed. + /// + /// This operation inserts the parsed decls into the translation + /// unit held by Ctx. + /// + /// \param CompleteTranslationUnit When true, the parsed file is + /// considered to be a complete translation unit, and any + /// end-of-translation-unit wrapup will be performed. + /// + /// \param CompletionConsumer If given, an object to consume code completion + /// results. + void ParseAST(Preprocessor &pp, ASTConsumer *C, + ASTContext &Ctx, bool PrintStats = false, + bool CompleteTranslationUnit = true, + CodeCompleteConsumer *CompletionConsumer = 0); + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h new file mode 100644 index 0000000..3689a6e --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h @@ -0,0 +1,48 @@ +//===--- SemaConsumer.h - Abstract interface for AST semantics --*- 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 SemaConsumer class, a subclass of +// ASTConsumer that is used by AST clients that also require +// additional semantic analysis. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_SEMACONSUMER_H +#define LLVM_CLANG_SEMA_SEMACONSUMER_H + +#include "clang/AST/ASTConsumer.h" + +namespace clang { + class Sema; + + /// \brief An abstract interface that should be implemented by + /// clients that read ASTs and then require further semantic + /// analysis of the entities in those ASTs. + class SemaConsumer : public ASTConsumer { + public: + SemaConsumer() { + ASTConsumer::SemaConsumer = true; + } + + /// \brief Initialize the semantic consumer with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S) {} + + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() {} + + // isa/cast/dyn_cast support + static bool classof(const ASTConsumer *Consumer) { + return Consumer->SemaConsumer; + } + static bool classof(const SemaConsumer *) { return true; } + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h new file mode 100644 index 0000000..a5a1364 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticSema.h - Diagnostics for libsema -------------*- 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_DIAGNOSTICSEMA_H +#define LLVM_CLANG_DIAGNOSTICSEMA_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define SEMASTART +#include "clang/Basic/DiagnosticSemaKinds.inc" +#undef DIAG + NUM_BUILTIN_SEMA_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif |