Update clang to r89205.
This commit is contained in:
parent
8f57cb0305
commit
b3d5a323a5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=199482
@ -94,6 +94,11 @@ install(DIRECTORY include/
|
||||
|
||||
add_definitions( -D_GNU_SOURCE )
|
||||
|
||||
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)
|
||||
if(CLANG_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(tools)
|
||||
|
6
Makefile
6
Makefile
@ -1,6 +1,12 @@
|
||||
LEVEL = ../..
|
||||
DIRS := include lib tools docs
|
||||
|
||||
PARALLEL_DIRS :=
|
||||
|
||||
ifeq ($(BUILD_EXAMPLES),1)
|
||||
PARALLEL_DIRS += examples
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
|
@ -50,7 +50,7 @@ TODO: File Manager Speedup:
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
// Specifying targets: -triple and -arch
|
||||
===---------------------------------------------------------------------===//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
The clang supports "-triple" and "-arch" options. At most one -triple and one
|
||||
-arch option may be specified. Both are optional.
|
||||
|
9
TODO.txt
9
TODO.txt
@ -66,3 +66,12 @@ More ideas for code modification hints:
|
||||
- If a class member is defined out-of-line but isn't in the class declaration (and there are no close matches!), provide the option to add an in-class declaration.
|
||||
- Fix-it hints for the inclusion of headers when needed for particular features (e.g., <typeinfo> for typeid)
|
||||
- Change "foo.bar" to "foo->bar" when "foo" is a pointer.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Options to support:
|
||||
-Wfatal-errors
|
||||
-ftabstop=width
|
||||
-fpreprocessed mode.
|
||||
-nostdinc++
|
||||
-imultilib
|
||||
|
@ -46,6 +46,9 @@
|
||||
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
|
||||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
|
||||
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
|
||||
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
|
||||
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; };
|
||||
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795310A90C6100741BBA /* TemplateBase.cpp */; };
|
||||
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
|
||||
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
|
||||
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */; };
|
||||
@ -362,6 +365,7 @@
|
||||
1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StmtXML.cpp; path = lib/Frontend/StmtXML.cpp; sourceTree = "<group>"; };
|
||||
1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Warnings.cpp; path = lib/Frontend/Warnings.cpp; sourceTree = "<group>"; };
|
||||
1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A31B27210ACE6DA009E0C8B /* GlobalDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = GlobalDecl.h; path = lib/CodeGen/GlobalDecl.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ExprConstant.cpp; path = lib/AST/ExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprConstant.cpp; path = lib/CodeGen/CGExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A471AB40F437BC500753CE8 /* CGBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBlocks.cpp; path = lib/CodeGen/CGBlocks.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
@ -396,6 +400,9 @@
|
||||
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1ADD795110A90C6100741BBA /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypePrinter.cpp; path = lib/AST/TypePrinter.cpp; sourceTree = "<group>"; };
|
||||
1ADD795210A90C6100741BBA /* TypeLoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeLoc.cpp; path = lib/AST/TypeLoc.cpp; sourceTree = "<group>"; };
|
||||
1ADD795310A90C6100741BBA /* TemplateBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateBase.cpp; path = lib/AST/TemplateBase.cpp; sourceTree = "<group>"; };
|
||||
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
@ -1289,6 +1296,7 @@
|
||||
DE928B7E0C0A615600231DA4 /* CodeGenModule.cpp */,
|
||||
DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */,
|
||||
DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */,
|
||||
1A31B27210ACE6DA009E0C8B /* GlobalDecl.h */,
|
||||
1A2193CC0F45EEB700C0713D /* Mangle.cpp */,
|
||||
1A2193CD0F45EEB700C0713D /* Mangle.h */,
|
||||
DE928B120C05659200231DA4 /* ModuleBuilder.cpp */,
|
||||
@ -1385,8 +1393,11 @@
|
||||
DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */,
|
||||
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */,
|
||||
35CFFDFF0CA1CBCB00E6F2BE /* StmtViz.cpp */,
|
||||
1ADD795310A90C6100741BBA /* TemplateBase.cpp */,
|
||||
DEDFF8870F848CF80035BD10 /* TemplateName.cpp */,
|
||||
DE75EDF00B06880E0020CF81 /* Type.cpp */,
|
||||
1ADD795210A90C6100741BBA /* TypeLoc.cpp */,
|
||||
1ADD795110A90C6100741BBA /* TypePrinter.cpp */,
|
||||
);
|
||||
name = AST;
|
||||
sourceTree = "<group>";
|
||||
@ -1919,6 +1930,9 @@
|
||||
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
|
||||
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */,
|
||||
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */,
|
||||
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */,
|
||||
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -126,7 +126,7 @@ reasonably possible, easing migration from GCC to Clang. In most cases, code
|
||||
|
||||
<p>In addition to language specific features, Clang has a variety of features
|
||||
that depend on what CPU architecture or operating system is being compiled for.
|
||||
Please see the <a href="target_features">Target-Specific Features and
|
||||
Please see the <a href="#target_features">Target-Specific Features and
|
||||
Limitations</a> section for more details.</p>
|
||||
|
||||
<p>The rest of the introduction introduces some basic <a
|
||||
|
@ -115,6 +115,26 @@ typedef struct {
|
||||
/* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */
|
||||
typedef void *CXEntity;
|
||||
|
||||
/**
|
||||
* For functions returning a string that might or might not need
|
||||
* to be internally allocated and freed.
|
||||
* Use clang_getCString to access the C string value.
|
||||
* Use clang_disposeString to free the value.
|
||||
* Treat it as an opaque type.
|
||||
*/
|
||||
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;
|
||||
|
||||
/* Get C string pointer from a CXString. */
|
||||
CINDEX_LINKAGE const char *clang_getCString(CXString string);
|
||||
|
||||
/* Free CXString. */
|
||||
CINDEX_LINKAGE void clang_disposeString(CXString string);
|
||||
|
||||
/**
|
||||
* \brief clang_createIndex() provides a shared context for creating
|
||||
* translation units. It provides two options:
|
||||
@ -155,8 +175,7 @@ typedef void *CXEntity;
|
||||
CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
|
||||
int displayDiagnostics);
|
||||
CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
|
||||
|
||||
CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
CINDEX_LINKAGE CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
|
||||
/*
|
||||
* \brief Create a translation unit from an AST file (-emit-ast).
|
||||
@ -260,7 +279,7 @@ CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
|
||||
*/
|
||||
CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
|
||||
CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
|
||||
CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
|
||||
CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl);
|
||||
CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
|
||||
CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
|
||||
CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
|
||||
@ -275,6 +294,8 @@ CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
|
||||
*/
|
||||
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column);
|
||||
|
||||
CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
|
||||
|
||||
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
|
||||
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
|
||||
@ -282,9 +303,11 @@ CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
|
||||
CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
|
||||
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
|
||||
|
||||
CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
|
||||
|
||||
CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
|
||||
CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
|
||||
CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
|
||||
CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
|
||||
CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
|
||||
CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
|
||||
|
||||
@ -305,6 +328,328 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
|
||||
*/
|
||||
CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
|
||||
|
||||
/**
|
||||
* \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 x"
|
||||
* - an Optional chunk containing the last defaulted argument:
|
||||
* - a Comma chunk for ","
|
||||
* - a Placeholder chunk for "double z"
|
||||
* - a RightParen chunk for ")"
|
||||
*
|
||||
* There are many ways two handle Optional chunks. Two simple approaches are:
|
||||
* - 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 Callback function that receives a single code-completion result.
|
||||
*
|
||||
* This callback will be invoked by \c clang_codeComplete() for each
|
||||
* code-completion result.
|
||||
*
|
||||
* \param completion_result a pointer to the current code-completion result,
|
||||
* providing one possible completion. The pointer itself is only valid
|
||||
* during the execution of the completion callback.
|
||||
*
|
||||
* \param client_data the client data provided to \c clang_codeComplete().
|
||||
*/
|
||||
typedef void (*CXCompletionIterator)(CXCompletionResult *completion_result,
|
||||
CXClientData client_data);
|
||||
|
||||
/**
|
||||
* \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 const char *
|
||||
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 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
|
||||
* enumerated through a callback interface to the client.
|
||||
*
|
||||
* 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-competion
|
||||
* 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 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 completion_iterator a callback function that will receive
|
||||
* code-completion results.
|
||||
*
|
||||
* \param client_data client-specific data that will be passed back via the
|
||||
* code-completion callback function.
|
||||
*/
|
||||
CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx,
|
||||
const char *source_filename,
|
||||
int num_command_line_args,
|
||||
const char **command_line_args,
|
||||
const char *complete_filename,
|
||||
unsigned complete_line,
|
||||
unsigned complete_column,
|
||||
CXCompletionIterator completion_iterator,
|
||||
CXClientData client_data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -37,6 +37,7 @@ namespace llvm {
|
||||
namespace clang {
|
||||
class FileManager;
|
||||
class ASTRecordLayout;
|
||||
class BlockExpr;
|
||||
class Expr;
|
||||
class ExternalASTSource;
|
||||
class IdentifierTable;
|
||||
@ -55,7 +56,6 @@ namespace clang {
|
||||
class TranslationUnitDecl;
|
||||
class TypeDecl;
|
||||
class TypedefDecl;
|
||||
class UnresolvedUsingDecl;
|
||||
class UsingDecl;
|
||||
|
||||
namespace Builtin { class Context; }
|
||||
@ -204,7 +204,7 @@ class ASTContext {
|
||||
///
|
||||
/// This mapping will contain an entry that maps from the UsingDecl in
|
||||
/// B<int> to the UnresolvedUsingDecl in B<T>.
|
||||
llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>
|
||||
llvm::DenseMap<UsingDecl *, NamedDecl *>
|
||||
InstantiatedFromUnresolvedUsingDecl;
|
||||
|
||||
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
|
||||
@ -232,7 +232,7 @@ class ASTContext {
|
||||
llvm::DenseMap<const Decl *, std::string> DeclComments;
|
||||
|
||||
public:
|
||||
TargetInfo &Target;
|
||||
const TargetInfo &Target;
|
||||
IdentifierTable &Idents;
|
||||
SelectorTable &Selectors;
|
||||
Builtin::Context &BuiltinInfo;
|
||||
@ -284,12 +284,11 @@ class ASTContext {
|
||||
|
||||
/// \brief If this using decl is instantiated from an unresolved using decl,
|
||||
/// return it.
|
||||
UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
|
||||
NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
|
||||
|
||||
/// \brief Note that the using decl \p Inst is an instantiation of
|
||||
/// the unresolved using decl \p Tmpl of a class template.
|
||||
void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst,
|
||||
UnresolvedUsingDecl *Tmpl);
|
||||
void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl);
|
||||
|
||||
|
||||
FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
|
||||
@ -319,7 +318,7 @@ class ASTContext {
|
||||
CanQualType UndeducedAutoTy;
|
||||
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
|
||||
|
||||
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
|
||||
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
|
||||
IdentifierTable &idents, SelectorTable &sels,
|
||||
Builtin::Context &builtins,
|
||||
bool FreeMemory = true, unsigned size_reserve=0);
|
||||
@ -672,6 +671,10 @@ class ASTContext {
|
||||
/// 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
|
||||
@ -872,9 +875,9 @@ class ASTContext {
|
||||
/// \brief Determine whether the given types are equivalent after
|
||||
/// cvr-qualifiers have been removed.
|
||||
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
|
||||
T1 = getCanonicalType(T1);
|
||||
T2 = getCanonicalType(T2);
|
||||
return T1.getUnqualifiedType() == T2.getUnqualifiedType();
|
||||
CanQualType CT1 = getCanonicalType(T1);
|
||||
CanQualType CT2 = getCanonicalType(T2);
|
||||
return CT1.getUnqualifiedType() == CT2.getUnqualifiedType();
|
||||
}
|
||||
|
||||
/// \brief Retrieves the "canonical" declaration of
|
||||
@ -925,6 +928,10 @@ class ASTContext {
|
||||
/// 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
|
||||
|
@ -50,6 +50,7 @@ class Attr {
|
||||
Annotate,
|
||||
AsmLabel, // Represent GCC asm label extension.
|
||||
Blocks,
|
||||
CDecl,
|
||||
Cleanup,
|
||||
Const,
|
||||
Constructor,
|
||||
@ -442,6 +443,7 @@ DEF_SIMPLE_ATTR(DLLImport);
|
||||
DEF_SIMPLE_ATTR(DLLExport);
|
||||
DEF_SIMPLE_ATTR(FastCall);
|
||||
DEF_SIMPLE_ATTR(StdCall);
|
||||
DEF_SIMPLE_ATTR(CDecl);
|
||||
DEF_SIMPLE_ATTR(TransparentUnion);
|
||||
DEF_SIMPLE_ATTR(ObjCNSObject);
|
||||
DEF_SIMPLE_ATTR(ObjCException);
|
||||
|
@ -71,6 +71,9 @@ class CanQual {
|
||||
/// \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();
|
||||
}
|
||||
@ -99,22 +102,22 @@ class CanQual {
|
||||
CanProxy<T> operator->() const;
|
||||
|
||||
/// \brief Retrieve all qualifiers.
|
||||
Qualifiers getQualifiers() const { return Stored.getQualifiers(); }
|
||||
Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
|
||||
|
||||
/// \brief Retrieve the const/volatile/restrict qualifiers.
|
||||
unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
|
||||
unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
|
||||
|
||||
/// \brief Determines whether this type has any qualifiers
|
||||
bool hasQualifiers() const { return Stored.hasQualifiers(); }
|
||||
bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
|
||||
|
||||
bool isConstQualified() const {
|
||||
return Stored.isConstQualified();
|
||||
return Stored.isLocalConstQualified();
|
||||
}
|
||||
bool isVolatileQualified() const {
|
||||
return Stored.isVolatileQualified();
|
||||
return Stored.isLocalVolatileQualified();
|
||||
}
|
||||
bool isRestrictQualified() const {
|
||||
return Stored.isRestrictQualified();
|
||||
return Stored.isLocalRestrictQualified();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the unqualified form of this type.
|
||||
@ -635,7 +638,7 @@ struct CanProxyAdaptor<ObjCObjectPointerType>
|
||||
//----------------------------------------------------------------------------//
|
||||
template<typename T>
|
||||
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
|
||||
return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType());
|
||||
return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -232,6 +232,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
|
||||
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
|
||||
|
||||
virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
|
||||
const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(getLocation(), RBracLoc);
|
||||
@ -552,6 +553,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
}
|
||||
|
||||
virtual VarDecl *getCanonicalDecl();
|
||||
const VarDecl *getCanonicalDecl() const {
|
||||
return const_cast<VarDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
/// hasLocalStorage - Returns true if a variable with function scope
|
||||
/// is a non-static local variable.
|
||||
@ -1424,6 +1428,9 @@ class TagDecl
|
||||
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 {
|
||||
@ -1515,6 +1522,9 @@ class EnumDecl : public TagDecl {
|
||||
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,
|
||||
|
@ -79,9 +79,11 @@ class Decl {
|
||||
/// namespaces, labels, tags, members and ordinary
|
||||
/// identifiers. These are meant as bitmasks, so that searches in
|
||||
/// C++ can look into the "tag" namespace during ordinary lookup. We
|
||||
/// use additional namespaces for Objective-C entities. We also
|
||||
/// put C++ friend declarations (of previously-undeclared entities) in
|
||||
/// shadow namespaces.
|
||||
/// use additional namespaces for Objective-C entities. We also put
|
||||
/// C++ friend declarations (of previously-undeclared entities) in
|
||||
/// shadow namespaces, and 'using' declarations (as opposed to their
|
||||
/// implicit shadow declarations) can be found in their own
|
||||
/// namespace.
|
||||
enum IdentifierNamespace {
|
||||
IDNS_Label = 0x1,
|
||||
IDNS_Tag = 0x2,
|
||||
@ -91,7 +93,8 @@ class Decl {
|
||||
IDNS_ObjCImplementation = 0x20,
|
||||
IDNS_ObjCCategoryImpl = 0x40,
|
||||
IDNS_OrdinaryFriend = 0x80,
|
||||
IDNS_TagFriend = 0x100
|
||||
IDNS_TagFriend = 0x100,
|
||||
IDNS_Using = 0x200
|
||||
};
|
||||
|
||||
/// ObjCDeclQualifier - Qualifier used on types in method declarations
|
||||
|
@ -432,6 +432,9 @@ class CXXRecordDecl : public RecordDecl {
|
||||
virtual CXXRecordDecl *getCanonicalDecl() {
|
||||
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||
}
|
||||
virtual const CXXRecordDecl *getCanonicalDecl() const {
|
||||
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||
}
|
||||
|
||||
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
@ -768,7 +771,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \param Base the base class we are searching for.
|
||||
///
|
||||
/// \returns true if this class is derived from Base, false otherwise.
|
||||
bool isDerivedFrom(CXXRecordDecl *Base);
|
||||
bool isDerivedFrom(CXXRecordDecl *Base) const;
|
||||
|
||||
/// \brief Determine whether this class is derived from the type \p Base.
|
||||
///
|
||||
@ -786,7 +789,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
|
||||
/// tangling input and output in \p Paths
|
||||
bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths);
|
||||
bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
|
||||
|
||||
/// \brief Function type used by lookupInBases() to determine whether a
|
||||
/// specific base class subobject matches the lookup criteria.
|
||||
@ -801,7 +804,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// lookupInBases().
|
||||
///
|
||||
/// \returns true if this base matched the search criteria, false otherwise.
|
||||
typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier,
|
||||
typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path,
|
||||
void *UserData);
|
||||
|
||||
@ -826,7 +829,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \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);
|
||||
CXXBasePaths &Paths) const;
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether the given
|
||||
/// base class specifier refers to a specific class declaration.
|
||||
@ -835,8 +838,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// 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(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
|
||||
void *BaseRecord);
|
||||
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *BaseRecord);
|
||||
|
||||
/// \brief Base-class lookup callback that determines whether there exists
|
||||
/// a tag with the given name.
|
||||
@ -844,8 +847,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// 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(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
|
||||
void *Name);
|
||||
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.
|
||||
@ -853,8 +856,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// 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(CXXBaseSpecifier *Specifier, CXXBasePath &Path,
|
||||
void *Name);
|
||||
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.
|
||||
@ -862,7 +865,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// 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(CXXBaseSpecifier *Specifier,
|
||||
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path,
|
||||
void *UserData);
|
||||
|
||||
@ -1244,6 +1247,11 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// 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 D->getKind() == CXXConstructor;
|
||||
@ -1261,13 +1269,6 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// };
|
||||
/// @endcode
|
||||
class CXXDestructorDecl : public CXXMethodDecl {
|
||||
public:
|
||||
enum KindOfObjectToDestroy {
|
||||
VBASE = 0x1,
|
||||
DRCTNONVBASE = 0x2,
|
||||
ANYBASE = 0x3
|
||||
};
|
||||
private:
|
||||
/// 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
|
||||
@ -1276,24 +1277,15 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
/// @c !Implicit && ImplicitlyDefined.
|
||||
bool ImplicitlyDefined : 1;
|
||||
|
||||
/// Support for base and member destruction.
|
||||
/// BaseOrMemberDestructions - The arguments used to destruct the base
|
||||
/// or member. Each uintptr_t value represents one of base classes (either
|
||||
/// virtual or direct non-virtual base), or non-static data member
|
||||
/// to be destroyed. The low two bits encode the kind of object
|
||||
/// being destroyed.
|
||||
uintptr_t *BaseOrMemberDestructions;
|
||||
unsigned NumBaseOrMemberDestructions;
|
||||
|
||||
FunctionDecl *OperatorDelete;
|
||||
|
||||
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline),
|
||||
ImplicitlyDefined(false),
|
||||
BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) {
|
||||
ImplicitlyDefined(false), OperatorDelete(0) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
@ -1319,95 +1311,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
ImplicitlyDefined = ID;
|
||||
}
|
||||
|
||||
/// destr_iterator - Iterates through the member/base destruction list.
|
||||
|
||||
/// destr_const_iterator - Iterates through the member/base destruction list.
|
||||
typedef uintptr_t const destr_const_iterator;
|
||||
|
||||
/// destr_begin() - Retrieve an iterator to the first destructed member/base.
|
||||
uintptr_t* destr_begin() {
|
||||
return BaseOrMemberDestructions;
|
||||
}
|
||||
/// destr_begin() - Retrieve an iterator to the first destructed member/base.
|
||||
uintptr_t* destr_begin() const {
|
||||
return BaseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// destr_end() - Retrieve an iterator past the last destructed member/base.
|
||||
uintptr_t* destr_end() {
|
||||
return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
|
||||
}
|
||||
/// destr_end() - Retrieve an iterator past the last destructed member/base.
|
||||
uintptr_t* destr_end() const {
|
||||
return BaseOrMemberDestructions + NumBaseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// getNumBaseOrMemberDestructions - Number of base and non-static members
|
||||
/// to destroy.
|
||||
unsigned getNumBaseOrMemberDestructions() const {
|
||||
return NumBaseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// setNumBaseOrMemberDestructions - Set number of base and non-static members
|
||||
/// to destroy.
|
||||
void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) {
|
||||
NumBaseOrMemberDestructions = numBaseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// getBaseOrMemberToDestroy - get the generic 'member' representing either
|
||||
/// the field or a base class.
|
||||
uintptr_t* getBaseOrMemberToDestroy() const {
|
||||
return BaseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// setBaseOrMemberToDestroy - set the generic 'member' representing either
|
||||
/// the field or a base class.
|
||||
void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) {
|
||||
BaseOrMemberDestructions = baseOrMemberDestructions;
|
||||
}
|
||||
|
||||
/// isVbaseToDestroy - returns true, if object is virtual base.
|
||||
bool isVbaseToDestroy(uintptr_t Vbase) const {
|
||||
return (Vbase & VBASE) != 0;
|
||||
}
|
||||
/// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual
|
||||
/// base.
|
||||
bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const {
|
||||
return (DrctNonVbase & DRCTNONVBASE) != 0;
|
||||
}
|
||||
/// isAnyBaseToDestroy - returns true, if object is any base (virtual or
|
||||
/// direct non-virtual)
|
||||
bool isAnyBaseToDestroy(uintptr_t AnyBase) const {
|
||||
return (AnyBase & ANYBASE) != 0;
|
||||
}
|
||||
/// isMemberToDestroy - returns true if object is a non-static data member.
|
||||
bool isMemberToDestroy(uintptr_t Member) const {
|
||||
return (Member & ANYBASE) == 0;
|
||||
}
|
||||
/// getAnyBaseClassToDestroy - Get the type for the given base class object.
|
||||
Type *getAnyBaseClassToDestroy(uintptr_t Base) const {
|
||||
if (isAnyBaseToDestroy(Base))
|
||||
return reinterpret_cast<Type*>(Base & ~0x03);
|
||||
return 0;
|
||||
}
|
||||
/// getMemberToDestroy - Get the member for the given object.
|
||||
FieldDecl *getMemberToDestroy(uintptr_t Member) const {
|
||||
if (isMemberToDestroy(Member))
|
||||
return reinterpret_cast<FieldDecl *>(Member);
|
||||
return 0;
|
||||
}
|
||||
/// getVbaseClassToDestroy - Get the virtual base.
|
||||
Type *getVbaseClassToDestroy(uintptr_t Vbase) const {
|
||||
if (isVbaseToDestroy(Vbase))
|
||||
return reinterpret_cast<Type*>(Vbase & ~0x01);
|
||||
return 0;
|
||||
}
|
||||
/// getDirectNonVBaseClassToDestroy - Get the virtual base.
|
||||
Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const {
|
||||
if (isDirectNonVBaseToDestroy(Base))
|
||||
return reinterpret_cast<Type*>(Base & ~0x02);
|
||||
return 0;
|
||||
}
|
||||
void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
|
||||
const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
@ -1739,6 +1644,56 @@ class NamespaceAliasDecl : public NamedDecl {
|
||||
static bool classof(const NamespaceAliasDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// Gets the underlying declaration which has been brought into the
|
||||
/// local scope.
|
||||
NamedDecl *getTargetDecl() const {
|
||||
return Underlying;
|
||||
}
|
||||
|
||||
/// Gets the using declaration to which this declaration is tied.
|
||||
UsingDecl *getUsingDecl() const {
|
||||
return Using;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UsingShadow;
|
||||
}
|
||||
static bool classof(const UsingShadowDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// UsingDecl - Represents a C++ using-declaration. For example:
|
||||
/// using someNameSpace::someIdentifier;
|
||||
class UsingDecl : public NamedDecl {
|
||||
@ -1746,29 +1701,26 @@ class UsingDecl : public NamedDecl {
|
||||
/// preceding the declaration name.
|
||||
SourceRange NestedNameRange;
|
||||
|
||||
/// \brief The source location of the target declaration name.
|
||||
SourceLocation TargetNameLocation;
|
||||
|
||||
/// \brief The source location of the "using" location itself.
|
||||
SourceLocation UsingLocation;
|
||||
|
||||
/// \brief Target declaration.
|
||||
NamedDecl* TargetDecl;
|
||||
|
||||
/// \brief Target nested name specifier.
|
||||
NestedNameSpecifier* TargetNestedNameDecl;
|
||||
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 TargetNL, SourceLocation UL, NamedDecl* Target,
|
||||
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
|
||||
: NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
|
||||
NestedNameRange(NNR), TargetNameLocation(TargetNL),
|
||||
UsingLocation(UL), TargetDecl(Target),
|
||||
TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
|
||||
this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
|
||||
SourceLocation UL, NestedNameSpecifier* TargetNNS,
|
||||
DeclarationName Name, bool IsTypeNameArg)
|
||||
: NamedDecl(Decl::Using, DC, L, Name),
|
||||
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
|
||||
IsTypeName(IsTypeNameArg) {
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1776,28 +1728,37 @@ class UsingDecl : public NamedDecl {
|
||||
/// preceding the namespace name.
|
||||
SourceRange getNestedNameRange() { return NestedNameRange; }
|
||||
|
||||
/// \brief Returns the source location of the target declaration name.
|
||||
SourceLocation getTargetNameLocation() { return TargetNameLocation; }
|
||||
|
||||
/// \brief Returns the source location of the "using" location itself.
|
||||
SourceLocation getUsingLocation() { return UsingLocation; }
|
||||
|
||||
/// \brief getTargetDecl - Returns target specified by using-decl.
|
||||
NamedDecl *getTargetDecl() { return TargetDecl; }
|
||||
const NamedDecl *getTargetDecl() const { return TargetDecl; }
|
||||
|
||||
/// \brief Get target nested name declaration.
|
||||
NestedNameSpecifier* getTargetNestedNameDecl() {
|
||||
return TargetNestedNameDecl;
|
||||
return TargetNestedName;
|
||||
}
|
||||
|
||||
/// isTypeName - Return true if using decl has 'typename'.
|
||||
bool isTypeName() const { return IsTypeName; }
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
|
||||
SourceLocation UL, NamedDecl* Target,
|
||||
NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
|
||||
SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
|
||||
NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::Using;
|
||||
@ -1805,31 +1766,33 @@ class UsingDecl : public NamedDecl {
|
||||
static bool classof(const UsingDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// UnresolvedUsingDecl - Represents a using declaration whose name can not
|
||||
/// yet be resolved.
|
||||
class UnresolvedUsingDecl : public NamedDecl {
|
||||
/// 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 target declaration name.
|
||||
SourceLocation TargetNameLocation;
|
||||
/// \brief The source location of the 'using' keyword
|
||||
SourceLocation UsingLocation;
|
||||
|
||||
NestedNameSpecifier *TargetNestedNameSpecifier;
|
||||
|
||||
DeclarationName TargetName;
|
||||
|
||||
// \brief Has 'typename' keyword.
|
||||
bool IsTypeName;
|
||||
|
||||
UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc,
|
||||
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
|
||||
SourceLocation TargetNameLoc, DeclarationName TargetName,
|
||||
bool IsTypeNameArg)
|
||||
: NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName),
|
||||
TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc),
|
||||
TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName),
|
||||
IsTypeName(IsTypeNameArg) { }
|
||||
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
|
||||
@ -1841,26 +1804,77 @@ class UnresolvedUsingDecl : public NamedDecl {
|
||||
return TargetNestedNameSpecifier;
|
||||
}
|
||||
|
||||
/// \brief Returns the source location of the target declaration name.
|
||||
SourceLocation getTargetNameLocation() const { return TargetNameLocation; }
|
||||
/// \brief Returns the source location of the 'using' keyword.
|
||||
SourceLocation getUsingLoc() const { return UsingLocation; }
|
||||
|
||||
/// \brief Returns the source location of the target declaration name.
|
||||
DeclarationName getTargetName() const { return TargetName; }
|
||||
|
||||
bool isTypeName() const { return IsTypeName; }
|
||||
|
||||
static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation UsingLoc,
|
||||
SourceRange TargetNNR,
|
||||
NestedNameSpecifier *TargetNNS,
|
||||
SourceLocation TargetNameLoc,
|
||||
DeclarationName TargetName,
|
||||
bool IsTypeNameArg);
|
||||
static UnresolvedUsingValueDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
|
||||
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
|
||||
SourceLocation TargetNameLoc, DeclarationName TargetName);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UnresolvedUsing;
|
||||
return D->getKind() == Decl::UnresolvedUsingValue;
|
||||
}
|
||||
static bool classof(const UnresolvedUsingDecl *D) { return true; }
|
||||
static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// 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 Get target nested name declaration.
|
||||
NestedNameSpecifier* getTargetNestedNameSpecifier() {
|
||||
return TargetNestedNameSpecifier;
|
||||
}
|
||||
|
||||
/// \brief Returns the source location of the 'using' keyword.
|
||||
SourceLocation getUsingLoc() const { return UsingLocation; }
|
||||
|
||||
/// \brief Returns the source location of the 'typename' keyword.
|
||||
SourceLocation getTypenameLoc() const { return TypenameLocation; }
|
||||
|
||||
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 D->getKind() == Decl::UnresolvedUsingTypename;
|
||||
}
|
||||
static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
|
||||
|
@ -14,8 +14,9 @@
|
||||
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
|
||||
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
|
||||
|
||||
#include "clang/AST/DeclBase.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"
|
||||
|
@ -81,6 +81,7 @@ ABSTRACT_DECL(Named, Decl)
|
||||
DECL(NamespaceAlias, NamedDecl)
|
||||
ABSTRACT_DECL(Type, NamedDecl)
|
||||
DECL(Typedef, TypeDecl)
|
||||
DECL(UnresolvedUsingTypename, TypeDecl)
|
||||
ABSTRACT_DECL(Tag, TypeDecl)
|
||||
DECL(Enum, TagDecl)
|
||||
DECL(Record, TagDecl)
|
||||
@ -91,6 +92,7 @@ ABSTRACT_DECL(Named, Decl)
|
||||
DECL(TemplateTypeParm, TypeDecl)
|
||||
ABSTRACT_DECL(Value, NamedDecl)
|
||||
DECL(EnumConstant, ValueDecl)
|
||||
DECL(UnresolvedUsingValue, ValueDecl)
|
||||
ABSTRACT_DECL(Declarator, ValueDecl)
|
||||
DECL(Function, DeclaratorDecl)
|
||||
DECL(CXXMethod, FunctionDecl)
|
||||
@ -109,7 +111,7 @@ ABSTRACT_DECL(Named, Decl)
|
||||
DECL(ClassTemplate, TemplateDecl)
|
||||
DECL(TemplateTemplateParm, TemplateDecl)
|
||||
DECL(Using, NamedDecl)
|
||||
DECL(UnresolvedUsing, NamedDecl)
|
||||
DECL(UsingShadow, NamedDecl)
|
||||
DECL(ObjCMethod, NamedDecl)
|
||||
DECL(ObjCContainer, NamedDecl)
|
||||
DECL(ObjCCategory, ObjCContainerDecl)
|
||||
|
@ -718,10 +718,22 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
|
||||
/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
|
||||
///
|
||||
class ObjCClassDecl : public Decl {
|
||||
ObjCList<ObjCInterfaceDecl> ForwardDecls;
|
||||
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, unsigned nElts, ASTContext &C);
|
||||
ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
|
||||
unsigned nElts, ASTContext &C);
|
||||
virtual ~ObjCClassDecl() {}
|
||||
public:
|
||||
|
||||
@ -730,17 +742,19 @@ class ObjCClassDecl : public Decl {
|
||||
|
||||
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 ObjCList<ObjCInterfaceDecl>::iterator iterator;
|
||||
iterator begin() const { return ForwardDecls.begin(); }
|
||||
iterator end() const { return ForwardDecls.end(); }
|
||||
unsigned size() const { return ForwardDecls.size(); }
|
||||
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, unsigned Num) {
|
||||
ForwardDecls.set(List, Num, C);
|
||||
}
|
||||
void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
|
||||
const SourceLocation *Locs, unsigned Num);
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
|
||||
static bool classof(const ObjCClassDecl *D) { return true; }
|
||||
|
@ -699,13 +699,13 @@ class TemplateTemplateParmDecl
|
||||
: public TemplateDecl, protected TemplateParmPosition {
|
||||
|
||||
/// \brief The default template argument, if any.
|
||||
Expr *DefaultArgument;
|
||||
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(0)
|
||||
TemplateParmPosition(D, P), DefaultArgument()
|
||||
{ }
|
||||
|
||||
public:
|
||||
@ -720,16 +720,17 @@ class TemplateTemplateParmDecl
|
||||
|
||||
/// \brief Determine whether this template parameter has a default
|
||||
/// argument.
|
||||
bool hasDefaultArgument() const { return DefaultArgument; }
|
||||
bool hasDefaultArgument() const {
|
||||
return !DefaultArgument.getArgument().isNull();
|
||||
}
|
||||
|
||||
/// \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;
|
||||
const TemplateArgumentLoc &getDefaultArgument() const {
|
||||
return DefaultArgument;
|
||||
}
|
||||
|
||||
/// \brief Set the default argument for this template parameter.
|
||||
void setDefaultArgument(Expr *DefArg) {
|
||||
void setDefaultArgument(const TemplateArgumentLoc &DefArg) {
|
||||
DefaultArgument = DefArg;
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,6 @@ class DeclarationName {
|
||||
/// getNameKind - Determine what kind of name this is.
|
||||
NameKind getNameKind() const;
|
||||
|
||||
|
||||
/// getName - Retrieve the human-readable string for this name.
|
||||
std::string getAsString() const;
|
||||
|
||||
@ -249,6 +248,8 @@ class DeclarationName {
|
||||
static DeclarationName getTombstoneMarker() {
|
||||
return DeclarationName(uintptr_t(-2));
|
||||
}
|
||||
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// Ordering on two declaration names. If both names are identifiers,
|
||||
|
@ -87,7 +87,7 @@ class Expr : public Stmt {
|
||||
// type. Additionally, inspect Expr::isLvalue to determine whether
|
||||
// an expression that is adjusted in this manner should be
|
||||
// considered an lvalue.
|
||||
assert((TR.isNull() || !TR->isReferenceType()) &&
|
||||
assert((t.isNull() || !t->isReferenceType()) &&
|
||||
"Expressions can't have reference type");
|
||||
|
||||
TR = t;
|
||||
@ -250,6 +250,12 @@ class Expr : public Stmt {
|
||||
/// 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;
|
||||
@ -1513,6 +1519,9 @@ class CastExpr : public Expr {
|
||||
/// 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,
|
||||
|
||||
|
@ -95,6 +95,8 @@ class CXXMemberCallExpr : public CallExpr {
|
||||
/// operation would return "x".
|
||||
Expr *getImplicitObjectArgument();
|
||||
|
||||
virtual SourceRange getSourceRange() const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXMemberCallExprClass;
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
#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;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_AST_REDECLARABLE_H
|
||||
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace clang {
|
||||
|
||||
@ -23,6 +24,8 @@ 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) { }
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
|
||||
namespace llvm {
|
||||
class FoldingSetNodeID;
|
||||
@ -48,21 +49,27 @@ class TemplateArgument {
|
||||
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 = 1,
|
||||
/// The template argument is a declaration
|
||||
Declaration = 2,
|
||||
/// The template argument is an integral value stored in an llvm::APSInt.
|
||||
Integral = 3,
|
||||
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 = 4,
|
||||
|
||||
Expression,
|
||||
/// The template argument is actually a parameter pack. Arguments are stored
|
||||
/// in the Args struct.
|
||||
Pack = 5
|
||||
Pack
|
||||
} Kind;
|
||||
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
@ -82,12 +89,21 @@ class TemplateArgument {
|
||||
}
|
||||
|
||||
/// \brief Construct an integral constant template argument.
|
||||
TemplateArgument(const llvm::APSInt &Value, QualType Type)
|
||||
: Kind(Integral) {
|
||||
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
|
||||
@ -172,6 +188,15 @@ class TemplateArgument {
|
||||
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)
|
||||
@ -242,13 +267,18 @@ struct TemplateArgumentLocInfo {
|
||||
union {
|
||||
Expr *Expression;
|
||||
DeclaratorInfo *Declarator;
|
||||
struct {
|
||||
unsigned QualifierRange[2];
|
||||
unsigned TemplateNameLoc;
|
||||
} Template;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
enum Kind {
|
||||
K_None,
|
||||
K_DeclaratorInfo,
|
||||
K_Expression
|
||||
K_Expression,
|
||||
K_Template
|
||||
} Kind;
|
||||
#endif
|
||||
|
||||
@ -273,6 +303,17 @@ struct TemplateArgumentLocInfo {
|
||||
, 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();
|
||||
}
|
||||
|
||||
DeclaratorInfo *getAsDeclaratorInfo() const {
|
||||
assert(Kind == K_DeclaratorInfo);
|
||||
@ -284,6 +325,18 @@ struct TemplateArgumentLocInfo {
|
||||
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()) {
|
||||
@ -294,6 +347,9 @@ struct TemplateArgumentLocInfo {
|
||||
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);
|
||||
@ -329,8 +385,18 @@ class TemplateArgumentLoc {
|
||||
assert(Argument.getKind() == TemplateArgument::Expression);
|
||||
}
|
||||
|
||||
/// \brief - Fetches the start location of the argument.
|
||||
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();
|
||||
}
|
||||
|
||||
@ -359,6 +425,16 @@ class TemplateArgumentLoc {
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -396,10 +396,6 @@ class QualType {
|
||||
llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
|
||||
Qualifiers::FastWidth> Value;
|
||||
|
||||
bool hasExtQuals() const {
|
||||
return Value.getPointer().is<const ExtQuals*>();
|
||||
}
|
||||
|
||||
const ExtQuals *getExtQualsUnsafe() const {
|
||||
return Value.getPointer().get<const ExtQuals*>();
|
||||
}
|
||||
@ -408,6 +404,8 @@ class QualType {
|
||||
return Value.getPointer().get<const Type*>();
|
||||
}
|
||||
|
||||
QualType getUnqualifiedTypeSlow() const;
|
||||
|
||||
friend class QualifierCollector;
|
||||
public:
|
||||
QualType() {}
|
||||
@ -417,14 +415,14 @@ class QualType {
|
||||
QualType(const ExtQuals *Ptr, unsigned Quals)
|
||||
: Value(Ptr, Quals) {}
|
||||
|
||||
unsigned getFastQualifiers() const { return Value.getInt(); }
|
||||
void setFastQualifiers(unsigned Quals) { Value.setInt(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 (hasNonFastQualifiers())
|
||||
if (hasLocalNonFastQualifiers())
|
||||
return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
|
||||
return const_cast<Type*>(getTypePtrUnsafe());
|
||||
}
|
||||
@ -452,41 +450,81 @@ class QualType {
|
||||
return Value.getPointer().isNull();
|
||||
}
|
||||
|
||||
bool isConstQualified() const {
|
||||
return (getFastQualifiers() & Qualifiers::Const);
|
||||
/// \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);
|
||||
}
|
||||
bool isRestrictQualified() const {
|
||||
return (getFastQualifiers() & Qualifiers::Restrict);
|
||||
|
||||
/// \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);
|
||||
}
|
||||
bool isVolatileQualified() const {
|
||||
return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
|
||||
|
||||
/// \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());
|
||||
}
|
||||
|
||||
// Determines whether this type has any direct qualifiers.
|
||||
bool hasQualifiers() const {
|
||||
return getFastQualifiers() || hasNonFastQualifiers();
|
||||
/// \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();
|
||||
}
|
||||
|
||||
bool hasNonFastQualifiers() const {
|
||||
return hasExtQuals();
|
||||
/// \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*>();
|
||||
}
|
||||
|
||||
// Retrieves the set of qualifiers belonging to this type.
|
||||
Qualifiers getQualifiers() const {
|
||||
/// \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 (hasNonFastQualifiers())
|
||||
if (hasLocalNonFastQualifiers())
|
||||
Quals = getExtQualsUnsafe()->getQualifiers();
|
||||
Quals.addFastQualifiers(getFastQualifiers());
|
||||
Quals.addFastQualifiers(getLocalFastQualifiers());
|
||||
return Quals;
|
||||
}
|
||||
|
||||
// Retrieves the CVR qualifiers of this type.
|
||||
unsigned getCVRQualifiers() const {
|
||||
unsigned CVR = getFastQualifiers();
|
||||
if (isVolatileQualified()) CVR |= Qualifiers::Volatile;
|
||||
/// \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;
|
||||
|
||||
bool isConstant(ASTContext& Ctx) const {
|
||||
return QualType::isConstant(*this, Ctx);
|
||||
}
|
||||
@ -508,6 +546,9 @@ class QualType {
|
||||
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();
|
||||
@ -540,8 +581,21 @@ class QualType {
|
||||
return T;
|
||||
}
|
||||
|
||||
QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); }
|
||||
/// \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;
|
||||
@ -892,8 +946,6 @@ class Type {
|
||||
|
||||
QualType getCanonicalTypeInternal() const { return CanonicalType; }
|
||||
void dump() const;
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const = 0;
|
||||
static bool classof(const Type *) { return true; }
|
||||
};
|
||||
|
||||
@ -963,8 +1015,21 @@ class BuiltinType : public Type {
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
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; }
|
||||
@ -988,9 +1053,6 @@ class FixedWidthIntType : public Type {
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; }
|
||||
static bool classof(const FixedWidthIntType *) { return true; }
|
||||
};
|
||||
@ -1008,9 +1070,6 @@ class ComplexType : public Type, public llvm::FoldingSetNode {
|
||||
public:
|
||||
QualType getElementType() const { return ElementType; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1036,9 +1095,6 @@ class PointerType : public Type, public llvm::FoldingSetNode {
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
@ -1071,9 +1127,6 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode {
|
||||
// Get the pointee type. Pointee is required to always be a function type.
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1157,9 +1210,6 @@ class LValueReferenceType : public ReferenceType {
|
||||
{}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1177,9 +1227,6 @@ class RValueReferenceType : public ReferenceType {
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1209,9 +1256,6 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
|
||||
|
||||
const Type *getClass() const { return Class; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1302,9 +1346,6 @@ class ConstantArrayType : public ArrayType {
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
const llvm::APInt &getSize() const { return Size; }
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1336,9 +1377,6 @@ class IncompleteArrayType : public ArrayType {
|
||||
: ArrayType(IncompleteArray, et, can, sm, tq) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1402,9 +1440,6 @@ class VariableArrayType : public ArrayType {
|
||||
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
|
||||
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1458,9 +1493,6 @@ class DependentSizedArrayType : public ArrayType {
|
||||
SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
|
||||
SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1510,9 +1542,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
|
||||
QualType getElementType() const { return ElementType; }
|
||||
SourceLocation getAttributeLoc() const { return loc; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1555,9 +1584,6 @@ class VectorType : public Type, public llvm::FoldingSetNode {
|
||||
QualType getElementType() const { return ElementType; }
|
||||
unsigned getNumElements() const { return NumElements; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1633,9 +1659,6 @@ class ExtVectorType : public VectorType {
|
||||
return unsigned(idx-1) < NumElements;
|
||||
return false;
|
||||
}
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1699,9 +1722,6 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
public:
|
||||
// No additional state past what FunctionType provides.
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1812,9 +1832,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
return exception_begin() + NumExceptions;
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -1856,9 +1873,6 @@ class TypedefType : public Type {
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const;
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
|
||||
static bool classof(const TypedefType *) { return true; }
|
||||
};
|
||||
@ -1879,9 +1893,6 @@ class TypeOfExprType : public Type {
|
||||
/// \brief Returns whether this type directly provides sugar.
|
||||
bool isSugared() const { return true; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
|
||||
static bool classof(const TypeOfExprType *) { return true; }
|
||||
};
|
||||
@ -1924,9 +1935,6 @@ class TypeOfType : public Type {
|
||||
/// \brief Returns whether this type directly provides sugar.
|
||||
bool isSugared() const { return true; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
|
||||
static bool classof(const TypeOfType *) { return true; }
|
||||
};
|
||||
@ -1953,9 +1961,6 @@ class DecltypeType : public Type {
|
||||
/// \brief Returns whether this type directly provides sugar.
|
||||
bool isSugared() const { return !isDependentType(); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
|
||||
static bool classof(const DecltypeType *) { return true; }
|
||||
};
|
||||
@ -2000,9 +2005,6 @@ class TagType : public Type {
|
||||
bool isBeingDefined() const { return decl.getInt(); }
|
||||
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
|
||||
}
|
||||
@ -2117,9 +2119,6 @@ class ElaboratedType : public Type, public llvm::FoldingSetNode {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getUnderlyingType(), getTagKind());
|
||||
}
|
||||
@ -2155,9 +2154,6 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
bool isParameterPack() const { return ParameterPack; }
|
||||
IdentifierInfo *getName() const { return Name; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -2211,9 +2207,6 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
return getCanonicalTypeInternal();
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const { return getReplacementType(); }
|
||||
|
||||
@ -2309,9 +2302,6 @@ class TemplateSpecializationType
|
||||
/// \precondition @c isArgType(Arg)
|
||||
const TemplateArgument &getArg(unsigned Idx) const;
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return !isDependentType(); }
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
@ -2363,9 +2353,6 @@ class QualifiedNameType : public Type, public llvm::FoldingSetNode {
|
||||
/// \brief Returns whether this type directly provides sugar.
|
||||
bool isSugared() const { return true; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, NNS, NamedType);
|
||||
}
|
||||
@ -2440,9 +2427,6 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
|
||||
return Name.dyn_cast<const TemplateSpecializationType *>();
|
||||
}
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -2493,9 +2477,6 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
|
||||
qual_iterator qual_end() const { return Protocols.end(); }
|
||||
bool qual_empty() const { return Protocols.size() == 0; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
@ -2581,8 +2562,6 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
|
||||
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCObjectPointer;
|
||||
}
|
||||
@ -2604,8 +2583,8 @@ class QualifierCollector : public Qualifiers {
|
||||
/// Collect any qualifiers on the given type and return an
|
||||
/// unqualified type.
|
||||
const Type *strip(QualType QT) {
|
||||
addFastQualifiers(QT.getFastQualifiers());
|
||||
if (QT.hasNonFastQualifiers()) {
|
||||
addFastQualifiers(QT.getLocalFastQualifiers());
|
||||
if (QT.hasLocalNonFastQualifiers()) {
|
||||
const ExtQuals *EQ = QT.getExtQualsUnsafe();
|
||||
Context = &EQ->getContext();
|
||||
addQualifiers(EQ->getQualifiers());
|
||||
@ -2627,18 +2606,51 @@ class QualifierCollector : public Qualifiers {
|
||||
|
||||
inline bool QualType::isCanonical() const {
|
||||
const Type *T = getTypePtr();
|
||||
if (hasQualifiers())
|
||||
if (hasLocalQualifiers())
|
||||
return T->isCanonicalUnqualified() && !isa<ArrayType>(T);
|
||||
return T->isCanonicalUnqualified();
|
||||
}
|
||||
|
||||
inline bool QualType::isCanonicalAsParam() const {
|
||||
if (hasQualifiers()) return false;
|
||||
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();
|
||||
}
|
||||
|
||||
inline void QualType::removeConst() {
|
||||
removeFastQualifiers(Qualifiers::Const);
|
||||
}
|
||||
@ -2673,14 +2685,14 @@ inline void QualType::removeCVRQualifiers(unsigned Mask) {
|
||||
|
||||
/// getAddressSpace - Return the address space of this type.
|
||||
inline unsigned QualType::getAddressSpace() const {
|
||||
if (hasNonFastQualifiers()) {
|
||||
if (hasLocalNonFastQualifiers()) {
|
||||
const ExtQuals *EQ = getExtQualsUnsafe();
|
||||
if (EQ->hasAddressSpace())
|
||||
return EQ->getAddressSpace();
|
||||
}
|
||||
|
||||
QualType CT = getTypePtr()->getCanonicalTypeInternal();
|
||||
if (CT.hasNonFastQualifiers()) {
|
||||
if (CT.hasLocalNonFastQualifiers()) {
|
||||
const ExtQuals *EQ = CT.getExtQualsUnsafe();
|
||||
if (EQ->hasAddressSpace())
|
||||
return EQ->getAddressSpace();
|
||||
@ -2695,14 +2707,14 @@ inline unsigned QualType::getAddressSpace() const {
|
||||
|
||||
/// getObjCGCAttr - Return the gc attribute of this type.
|
||||
inline Qualifiers::GC QualType::getObjCGCAttr() const {
|
||||
if (hasNonFastQualifiers()) {
|
||||
if (hasLocalNonFastQualifiers()) {
|
||||
const ExtQuals *EQ = getExtQualsUnsafe();
|
||||
if (EQ->hasObjCGCAttr())
|
||||
return EQ->getObjCGCAttr();
|
||||
}
|
||||
|
||||
QualType CT = getTypePtr()->getCanonicalTypeInternal();
|
||||
if (CT.hasNonFastQualifiers()) {
|
||||
if (CT.hasLocalNonFastQualifiers()) {
|
||||
const ExtQuals *EQ = CT.getExtQualsUnsafe();
|
||||
if (EQ->hasObjCGCAttr())
|
||||
return EQ->getObjCGCAttr();
|
||||
@ -2780,28 +2792,26 @@ inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: All of these methods use "getUnqualifiedType" to strip off address
|
||||
// space qualifiers if present.
|
||||
inline bool Type::isFunctionType() const {
|
||||
return isa<FunctionType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<FunctionType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isPointerType() const {
|
||||
return isa<PointerType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<PointerType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isAnyPointerType() const {
|
||||
return isPointerType() || isObjCObjectPointerType();
|
||||
}
|
||||
inline bool Type::isBlockPointerType() const {
|
||||
return isa<BlockPointerType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<BlockPointerType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isReferenceType() const {
|
||||
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ReferenceType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isLValueReferenceType() const {
|
||||
return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<LValueReferenceType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isRValueReferenceType() const {
|
||||
return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<RValueReferenceType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isFunctionPointerType() const {
|
||||
if (const PointerType* T = getAs<PointerType>())
|
||||
@ -2810,7 +2820,7 @@ inline bool Type::isFunctionPointerType() const {
|
||||
return false;
|
||||
}
|
||||
inline bool Type::isMemberPointerType() const {
|
||||
return isa<MemberPointerType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<MemberPointerType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isMemberFunctionPointerType() const {
|
||||
if (const MemberPointerType* T = getAs<MemberPointerType>())
|
||||
@ -2819,37 +2829,37 @@ inline bool Type::isMemberFunctionPointerType() const {
|
||||
return false;
|
||||
}
|
||||
inline bool Type::isArrayType() const {
|
||||
return isa<ArrayType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ArrayType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isConstantArrayType() const {
|
||||
return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ConstantArrayType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isIncompleteArrayType() const {
|
||||
return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<IncompleteArrayType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isVariableArrayType() const {
|
||||
return isa<VariableArrayType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<VariableArrayType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isDependentSizedArrayType() const {
|
||||
return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<DependentSizedArrayType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isRecordType() const {
|
||||
return isa<RecordType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<RecordType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isAnyComplexType() const {
|
||||
return isa<ComplexType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ComplexType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isVectorType() const {
|
||||
return isa<VectorType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<VectorType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isExtVectorType() const {
|
||||
return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ExtVectorType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isObjCObjectPointerType() const {
|
||||
return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ObjCObjectPointerType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isObjCInterfaceType() const {
|
||||
return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<ObjCInterfaceType>(CanonicalType);
|
||||
}
|
||||
inline bool Type::isObjCQualifiedIdType() const {
|
||||
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
|
||||
@ -2875,7 +2885,7 @@ inline bool Type::isObjCBuiltinType() const {
|
||||
return isObjCIdType() || isObjCClassType();
|
||||
}
|
||||
inline bool Type::isTemplateTypeParmType() const {
|
||||
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
|
||||
return isa<TemplateTypeParmType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isSpecificBuiltinType(unsigned K) const {
|
||||
@ -2911,8 +2921,21 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
return DB;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
@ -58,7 +58,7 @@ class TypeLoc {
|
||||
: Ty(ty), Data(opaqueData) { }
|
||||
|
||||
TypeLocClass getTypeLocClass() const {
|
||||
if (getType().hasQualifiers()) return Qualified;
|
||||
if (getType().hasLocalQualifiers()) return Qualified;
|
||||
return (TypeLocClass) getType()->getTypeClass();
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ class UnqualTypeLoc : public TypeLoc {
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return !TL->getType().hasQualifiers();
|
||||
return !TL->getType().hasLocalQualifiers();
|
||||
}
|
||||
static bool classof(const UnqualTypeLoc *TL) { return true; }
|
||||
};
|
||||
@ -196,11 +196,11 @@ class QualifiedTypeLoc : public TypeLoc {
|
||||
/// \brief Returns the size of the type source info data block.
|
||||
unsigned getFullDataSize() const {
|
||||
return getLocalDataSize() +
|
||||
getFullDataSizeForType(getType().getUnqualifiedType());
|
||||
getFullDataSizeForType(getType().getLocalUnqualifiedType());
|
||||
}
|
||||
|
||||
static bool classof(const TypeLoc *TL) {
|
||||
return TL->getType().hasQualifiers();
|
||||
return TL->getType().hasLocalQualifiers();
|
||||
}
|
||||
static bool classof(const QualifiedTypeLoc *TL) { return true; }
|
||||
};
|
||||
@ -919,6 +919,10 @@ class TemplateSpecializationTypeLoc :
|
||||
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Template:
|
||||
Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
|
||||
break;
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -88,11 +88,11 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
|
||||
|
||||
/// dumpLiveness - Print to stderr the liveness information encoded
|
||||
/// by a specified bitvector.
|
||||
void dumpLiveness(const ValTy& V, SourceManager& M) const;
|
||||
void dumpLiveness(const ValTy& V, const SourceManager& M) const;
|
||||
|
||||
/// dumpBlockLiveness - Print to stderr the liveness information
|
||||
/// associated with each basic block.
|
||||
void dumpBlockLiveness(SourceManager& M) const;
|
||||
void dumpBlockLiveness(const SourceManager& M) const;
|
||||
|
||||
/// getNumDecls - Return the number of variables (declarations) that
|
||||
/// whose liveness status is being tracked by the dataflow
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "functional" // STL
|
||||
|
||||
|
@ -50,10 +50,12 @@ void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID,
|
||||
void CheckObjCUnusedIvar(const ObjCImplementationDecl *D, BugReporter& BR);
|
||||
|
||||
void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D);
|
||||
void RegisterExperimentalChecks(GRExprEngine &Eng);
|
||||
void RegisterExperimentalInternalChecks(GRExprEngine &Eng);
|
||||
|
||||
void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR);
|
||||
|
||||
|
||||
void CheckSizeofPointer(const Decl *D, BugReporter &BR);
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
53
include/clang/Analysis/ManagerRegistry.h
Normal file
53
include/clang/Analysis/ManagerRegistry.h
Normal file
@ -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/Analysis/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
|
@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
@ -37,7 +37,6 @@ class AnalysisManager : public BugReporterData {
|
||||
|
||||
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
|
||||
|
||||
bool DisplayedFunction;
|
||||
bool VisualizeEGDot;
|
||||
bool VisualizeEGUbi;
|
||||
bool PurgeDead;
|
||||
@ -62,7 +61,7 @@ class AnalysisManager : public BugReporterData {
|
||||
|
||||
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
|
||||
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
|
||||
AScope(ScopeDecl), DisplayedFunction(!displayProgress),
|
||||
AScope(ScopeDecl),
|
||||
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
|
||||
EagerlyAssume(eager), TrimGraph(trim) {}
|
||||
|
||||
@ -120,8 +119,6 @@ class AnalysisManager : public BugReporterData {
|
||||
|
||||
bool shouldEagerlyAssume() const { return EagerlyAssume; }
|
||||
|
||||
void DisplayFunction(Decl *D);
|
||||
|
||||
CFG *getCFG(Decl const *D) {
|
||||
return AnaCtxMgr.getContext(D)->getCFG();
|
||||
}
|
||||
|
@ -81,10 +81,10 @@ class BugReport : public BugReporterVisitor {
|
||||
getOriginalNode(const ExplodedNode* N) = 0;
|
||||
};
|
||||
|
||||
BugReport(BugType& bt, const char* desc, const ExplodedNode *n)
|
||||
BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n)
|
||||
: BT(bt), Description(desc), EndNode(n) {}
|
||||
|
||||
BugReport(BugType& bt, const char* shortDesc, const char* desc,
|
||||
BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc,
|
||||
const ExplodedNode *n)
|
||||
: BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {}
|
||||
|
||||
@ -193,11 +193,11 @@ class BugReportEquivClass : public llvm::FoldingSetNode {
|
||||
class RangedBugReport : public BugReport {
|
||||
std::vector<SourceRange> Ranges;
|
||||
public:
|
||||
RangedBugReport(BugType& D, const char* description, ExplodedNode *n)
|
||||
RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
|
||||
: BugReport(D, description, n) {}
|
||||
|
||||
RangedBugReport(BugType& D, const char *shortDescription,
|
||||
const char *description, ExplodedNode *n)
|
||||
RangedBugReport(BugType& D, llvm::StringRef shortDescription,
|
||||
llvm::StringRef description, ExplodedNode *n)
|
||||
: BugReport(D, shortDescription, description, n) {}
|
||||
|
||||
~RangedBugReport();
|
||||
@ -229,11 +229,11 @@ class EnhancedBugReport : public RangedBugReport {
|
||||
Creators creators;
|
||||
|
||||
public:
|
||||
EnhancedBugReport(BugType& D, const char* description, ExplodedNode *n)
|
||||
EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
|
||||
: RangedBugReport(D, description, n) {}
|
||||
|
||||
EnhancedBugReport(BugType& D, const char *shortDescription,
|
||||
const char *description, ExplodedNode *n)
|
||||
EnhancedBugReport(BugType& D, llvm::StringRef shortDescription,
|
||||
llvm::StringRef description, ExplodedNode *n)
|
||||
: RangedBugReport(D, shortDescription, description, n) {}
|
||||
|
||||
~EnhancedBugReport() {}
|
||||
|
@ -23,6 +23,7 @@ class BugReportEquivClass;
|
||||
class BugReporter;
|
||||
class BuiltinBugReport;
|
||||
class BugReporterContext;
|
||||
class ExplodedNode;
|
||||
class GRExprEngine;
|
||||
|
||||
class BugType {
|
||||
@ -59,21 +60,27 @@ class BugType {
|
||||
};
|
||||
|
||||
class BuiltinBug : public BugType {
|
||||
GRExprEngine &Eng;
|
||||
GRExprEngine *Eng;
|
||||
protected:
|
||||
const std::string desc;
|
||||
public:
|
||||
BuiltinBug(const char *name, const char *description)
|
||||
: BugType(name, "Logic error"), Eng(0), desc(description) {}
|
||||
|
||||
BuiltinBug(const char *name)
|
||||
: BugType(name, "Logic error"), Eng(0), desc(name) {}
|
||||
|
||||
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
|
||||
: BugType(n, "Logic error"), Eng(*eng), desc(d) {}
|
||||
: BugType(n, "Logic error"), Eng(eng), desc(d) {}
|
||||
|
||||
BuiltinBug(GRExprEngine *eng, const char* n)
|
||||
: BugType(n, "Logic error"), Eng(*eng), desc(n) {}
|
||||
: BugType(n, "Logic error"), Eng(eng), desc(n) {}
|
||||
|
||||
const std::string &getDescription() const { return desc; }
|
||||
|
||||
virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
|
||||
|
||||
void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
|
||||
void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); }
|
||||
|
||||
virtual void registerInitialVisitors(BugReporterContext& BRC,
|
||||
const ExplodedNode* N,
|
||||
|
@ -39,22 +39,19 @@ class CheckerContext {
|
||||
SaveAndRestore<const void*> OldTag;
|
||||
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
|
||||
SaveOr OldHasGen;
|
||||
const GRState *state;
|
||||
|
||||
public:
|
||||
CheckerContext(ExplodedNodeSet &dst,
|
||||
GRStmtNodeBuilder &builder,
|
||||
GRExprEngine &eng,
|
||||
ExplodedNode *pred,
|
||||
const void *tag, bool preVisit)
|
||||
CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
|
||||
GRExprEngine &eng, ExplodedNode *pred,
|
||||
const void *tag, ProgramPoint::Kind K,
|
||||
const GRState *st = 0)
|
||||
: Dst(dst), B(builder), Eng(eng), Pred(pred),
|
||||
OldSink(B.BuildSinks), OldTag(B.Tag),
|
||||
OldPointKind(B.PointKind), OldHasGen(B.HasGeneratedNode) {
|
||||
//assert(Dst.empty()); // This is a fake assertion.
|
||||
// See GRExprEngine::CheckerVisit(), CurrSet is repeatedly used.
|
||||
B.Tag = tag;
|
||||
if (preVisit)
|
||||
B.PointKind = ProgramPoint::PreStmtKind;
|
||||
}
|
||||
OldSink(B.BuildSinks),
|
||||
OldTag(B.Tag, tag),
|
||||
OldPointKind(B.PointKind, K),
|
||||
OldHasGen(B.HasGeneratedNode),
|
||||
state(st) {}
|
||||
|
||||
~CheckerContext() {
|
||||
if (!B.BuildSinks && !B.HasGeneratedNode)
|
||||
@ -64,10 +61,15 @@ class CheckerContext {
|
||||
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 B.GetState(Pred); }
|
||||
const GRState *getState() { return state ? state : B.GetState(Pred); }
|
||||
|
||||
ASTContext &getASTContext() {
|
||||
return Eng.getContext();
|
||||
@ -76,6 +78,10 @@ class CheckerContext {
|
||||
BugReporter &getBugReporter() {
|
||||
return Eng.getBugReporter();
|
||||
}
|
||||
|
||||
SourceManager &getSourceManager() {
|
||||
return getBugReporter().getSourceManager();
|
||||
}
|
||||
|
||||
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
|
||||
return GenerateNode(S, getState(), markAsSink);
|
||||
@ -104,50 +110,69 @@ class Checker {
|
||||
private:
|
||||
friend class GRExprEngine;
|
||||
|
||||
// FIXME: Remove the 'tag' option.
|
||||
void GR_Visit(ExplodedNodeSet &Dst,
|
||||
GRStmtNodeBuilder &Builder,
|
||||
GRExprEngine &Eng,
|
||||
const Stmt *stmt,
|
||||
const Stmt *S,
|
||||
ExplodedNode *Pred, void *tag, bool isPrevisit) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
|
||||
assert(isPrevisit && "Only previsit supported for now.");
|
||||
_PreVisit(C, stmt);
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag,
|
||||
isPrevisit ? ProgramPoint::PreStmtKind :
|
||||
ProgramPoint::PostStmtKind);
|
||||
if (isPrevisit)
|
||||
_PreVisit(C, S);
|
||||
else
|
||||
_PostVisit(C, S);
|
||||
}
|
||||
|
||||
// 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);
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag,
|
||||
isPrevisit ? ProgramPoint::PreStmtKind :
|
||||
ProgramPoint::PostStmtKind);
|
||||
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, 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, Pred->getState());
|
||||
EvalDeadSymbols(C, S, SymReaper);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Checker() {}
|
||||
virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {}
|
||||
|
||||
// This is a previsit which takes a node returns a node.
|
||||
virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
|
||||
const GRState *state, SVal V,
|
||||
GRExprEngine &Eng) {
|
||||
return Pred;
|
||||
}
|
||||
|
||||
virtual void PreVisitBind(CheckerContext &C,
|
||||
const Stmt *AssignE, const Stmt *StoreE,
|
||||
SVal location, SVal val) {}
|
||||
|
||||
virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
||||
const GRState *state, Stmt *S,
|
||||
GRExprEngine &Eng) {
|
||||
return Pred;
|
||||
}
|
||||
|
||||
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) {}
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
@ -11,8 +11,19 @@
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
PREVISIT(CallExpr)
|
||||
PREVISIT(ObjCMessageExpr)
|
||||
#ifdef PREVISIT
|
||||
PREVISIT(ArraySubscriptExpr)
|
||||
PREVISIT(BinaryOperator)
|
||||
|
||||
PREVISIT(CallExpr)
|
||||
PREVISIT(CastExpr)
|
||||
PREVISIT(DeclStmt)
|
||||
PREVISIT(ObjCMessageExpr)
|
||||
PREVISIT(ReturnStmt)
|
||||
#undef PREVISIT
|
||||
#endif
|
||||
|
||||
#ifdef POSTVISIT
|
||||
POSTVISIT(CallExpr)
|
||||
#undef POSTVISIT
|
||||
#endif
|
||||
|
||||
|
@ -27,8 +27,12 @@ namespace clang {
|
||||
template<typename ImplClass>
|
||||
class CheckerVisitor : public Checker {
|
||||
public:
|
||||
virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) {
|
||||
PreVisit(C, stmt);
|
||||
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) {
|
||||
@ -36,14 +40,37 @@ class CheckerVisitor : public Checker {
|
||||
default:
|
||||
assert(false && "Unsupport statement.");
|
||||
return;
|
||||
|
||||
case Stmt::ImplicitCastExprClass:
|
||||
case Stmt::ExplicitCastExprClass:
|
||||
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) \
|
||||
case Stmt::NAME ## Class:\
|
||||
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
|
||||
break;
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
}
|
||||
}
|
||||
|
||||
void PostVisit(CheckerContext &C, const Stmt *S) {
|
||||
switch (S->getStmtClass()) {
|
||||
default:
|
||||
assert(false && "Unsupport statement.");
|
||||
return;
|
||||
#define POSTVISIT(NAME) \
|
||||
case Stmt::NAME ## Class:\
|
||||
static_cast<ImplClass*>(this)->\
|
||||
PostVisit ## NAME(C,static_cast<const NAME*>(S));\
|
||||
break;
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
}
|
||||
}
|
||||
@ -51,9 +78,12 @@ break;
|
||||
#define PREVISIT(NAME) \
|
||||
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {}
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
|
||||
#define POSTVISIT(NAME) \
|
||||
void PostVisit ## NAME(CheckerContext &C, const NAME* S) {}
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -16,38 +16,16 @@
|
||||
#ifndef LLVM_CLANG_DEREFCHECKER
|
||||
#define LLVM_CLANG_DEREFCHECKER
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checker.h"
|
||||
#include "clang/Analysis/PathSensitive/BugType.h"
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class GRExprEngine;
|
||||
class ExplodedNode;
|
||||
|
||||
class NullDerefChecker : public Checker {
|
||||
BuiltinBug *BT;
|
||||
llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
|
||||
|
||||
public:
|
||||
NullDerefChecker() : BT(0) {}
|
||||
ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
|
||||
const GRState *state, SVal V,GRExprEngine &Eng);
|
||||
|
||||
static void *getTag();
|
||||
typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator;
|
||||
iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); }
|
||||
iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); }
|
||||
};
|
||||
|
||||
class UndefDerefChecker : public Checker {
|
||||
BuiltinBug *BT;
|
||||
public:
|
||||
UndefDerefChecker() : BT(0) {}
|
||||
|
||||
ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
|
||||
const GRState *state, SVal V, GRExprEngine &Eng);
|
||||
|
||||
static void *getTag();
|
||||
};
|
||||
std::pair<ExplodedNode * const *, ExplodedNode * const *>
|
||||
GetImplicitNullDereferences(GRExprEngine &Eng);
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
@ -111,14 +111,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
// was larger than sizeof(void *) (an undefined value).
|
||||
ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit;
|
||||
|
||||
/// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
|
||||
/// the address of a stack variable.
|
||||
ErrorNodes RetsStackAddr;
|
||||
|
||||
/// RetsUndef - Nodes in the ExplodedGraph that result from returning
|
||||
/// an undefined value.
|
||||
ErrorNodes RetsUndef;
|
||||
|
||||
/// UndefBranches - Nodes in the ExplodedGraph that result from
|
||||
/// taking a branch based on an undefined value.
|
||||
ErrorNodes UndefBranches;
|
||||
@ -131,22 +123,10 @@ class GRExprEngine : public GRSubEngine {
|
||||
// calling a function with the attribute "noreturn".
|
||||
ErrorNodes NoReturnCalls;
|
||||
|
||||
/// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
|
||||
/// constructing a zero-sized VLA where the size may be zero.
|
||||
ErrorNodes ImplicitBadSizedVLA;
|
||||
|
||||
/// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
|
||||
/// constructing a zero-sized VLA where the size must be zero.
|
||||
ErrorNodes ExplicitBadSizedVLA;
|
||||
|
||||
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
|
||||
/// by the result is not. Excludes divide-by-zero errors.
|
||||
ErrorNodes UndefResults;
|
||||
|
||||
/// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
|
||||
/// pointers that are NULL (or other constants) or Undefined.
|
||||
ErrorNodes BadCalls;
|
||||
|
||||
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
|
||||
/// ObjC message expressions where the receiver is undefined (uninitialized).
|
||||
ErrorNodes UndefReceivers;
|
||||
@ -156,14 +136,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
/// value.
|
||||
UndefArgsTy MsgExprUndefArgs;
|
||||
|
||||
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
|
||||
/// out-of-bound memory accesses where the index MAY be out-of-bound.
|
||||
ErrorNodes ImplicitOOBMemAccesses;
|
||||
|
||||
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
|
||||
/// out-of-bound memory accesses where the index MUST be out-of-bound.
|
||||
ErrorNodes ExplicitOOBMemAccesses;
|
||||
|
||||
public:
|
||||
GRExprEngine(AnalysisManager &mgr);
|
||||
|
||||
@ -223,58 +195,10 @@ class GRExprEngine : public GRSubEngine {
|
||||
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
|
||||
}
|
||||
|
||||
bool isRetStackAddr(const ExplodedNode* N) const {
|
||||
return N->isSink() && RetsStackAddr.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isUndefControlFlow(const ExplodedNode* N) const {
|
||||
return N->isSink() && UndefBranches.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isUndefStore(const ExplodedNode* N) const {
|
||||
return N->isSink() && UndefStores.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isImplicitNullDeref(const ExplodedNode* N) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isExplicitNullDeref(const ExplodedNode* N) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefDeref(const ExplodedNode* N) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNoReturnCall(const ExplodedNode* N) const {
|
||||
return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isUndefResult(const ExplodedNode* N) const {
|
||||
return N->isSink() && UndefResults.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isBadCall(const ExplodedNode* N) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefArg(const ExplodedNode* N) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefReceiver(const ExplodedNode* N) const {
|
||||
return N->isSink() && UndefReceivers.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
}
|
||||
|
||||
typedef ErrorNodes::iterator ret_stackaddr_iterator;
|
||||
ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
|
||||
ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
|
||||
|
||||
typedef ErrorNodes::iterator ret_undef_iterator;
|
||||
ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
|
||||
ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
|
||||
|
||||
typedef ErrorNodes::iterator undef_branch_iterator;
|
||||
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
|
||||
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
|
||||
@ -305,10 +229,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
|
||||
undef_result_iterator undef_results_end() { return UndefResults.end(); }
|
||||
|
||||
typedef ErrorNodes::iterator bad_calls_iterator;
|
||||
bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
|
||||
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
|
||||
|
||||
typedef UndefArgsTy::iterator undef_arg_iterator;
|
||||
undef_arg_iterator msg_expr_undef_arg_begin() {
|
||||
return MsgExprUndefArgs.begin();
|
||||
@ -327,20 +247,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
return UndefReceivers.end();
|
||||
}
|
||||
|
||||
typedef ErrorNodes::iterator oob_memacc_iterator;
|
||||
oob_memacc_iterator implicit_oob_memacc_begin() {
|
||||
return ImplicitOOBMemAccesses.begin();
|
||||
}
|
||||
oob_memacc_iterator implicit_oob_memacc_end() {
|
||||
return ImplicitOOBMemAccesses.end();
|
||||
}
|
||||
oob_memacc_iterator explicit_oob_memacc_begin() {
|
||||
return ExplicitOOBMemAccesses.begin();
|
||||
}
|
||||
oob_memacc_iterator explicit_oob_memacc_end() {
|
||||
return ExplicitOOBMemAccesses.end();
|
||||
}
|
||||
|
||||
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
|
||||
void AddCheck(GRSimpleAPICheck* A);
|
||||
|
||||
@ -368,10 +274,7 @@ class GRExprEngine : public GRSubEngine {
|
||||
|
||||
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
|
||||
/// nodes when the control reaches the end of a function.
|
||||
void ProcessEndPath(GREndPathNodeBuilder& builder) {
|
||||
getTF().EvalEndPath(*this, builder);
|
||||
StateMgr.EndPath(builder.getState());
|
||||
}
|
||||
void ProcessEndPath(GREndPathNodeBuilder& builder);
|
||||
|
||||
GRStateManager& getStateManager() { return StateMgr; }
|
||||
const GRStateManager& getStateManager() const { return StateMgr; }
|
||||
@ -516,9 +419,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst,
|
||||
bool asLValue);
|
||||
|
||||
const GRState* CheckDivideZero(Expr* Ex, const GRState* St, ExplodedNode* Pred,
|
||||
SVal Denom);
|
||||
|
||||
/// 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.
|
||||
@ -553,15 +453,11 @@ class GRExprEngine : public GRSubEngine {
|
||||
}
|
||||
|
||||
protected:
|
||||
void EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, ExplodedNode* Pred);
|
||||
|
||||
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) {
|
||||
assert (Builder && "GRStmtNodeBuilder must be defined.");
|
||||
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
|
||||
}
|
||||
|
||||
void EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* s, ExplodedNode* Pred);
|
||||
|
||||
const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
|
||||
bool branchTaken);
|
||||
|
||||
@ -573,16 +469,22 @@ class GRExprEngine : public GRSubEngine {
|
||||
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);
|
||||
const GRState* St, SVal location, const void *tag = 0,
|
||||
QualType LoadTy = QualType());
|
||||
|
||||
ExplodedNode* EvalLocation(Stmt* Ex, ExplodedNode* Pred,
|
||||
// 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 = 0);
|
||||
const void *tag, bool isLoad);
|
||||
|
||||
// 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,
|
||||
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
|
||||
const void *tag = 0);
|
||||
};
|
||||
|
||||
|
@ -195,6 +195,9 @@ class GRState : public llvm::FoldingSetNode {
|
||||
//
|
||||
|
||||
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,
|
||||
@ -330,12 +333,6 @@ class GRState : public llvm::FoldingSetNode {
|
||||
void printStdErr() const;
|
||||
|
||||
void printDOT(llvm::raw_ostream& Out) const;
|
||||
|
||||
// Tags used for the Generic Data Map.
|
||||
struct NullDerefTag {
|
||||
static int TagInt;
|
||||
typedef const SVal* data_type;
|
||||
};
|
||||
};
|
||||
|
||||
class GRStateSet {
|
||||
@ -403,10 +400,6 @@ class GRStateManager {
|
||||
/// Alloc - A BumpPtrAllocator to allocate states.
|
||||
llvm::BumpPtrAllocator& Alloc;
|
||||
|
||||
/// CurrentStmt - The block-level statement currently being visited. This
|
||||
/// is set by GRExprEngine.
|
||||
Stmt* CurrentStmt;
|
||||
|
||||
/// TF - Object that represents a bundle of transfer functions
|
||||
/// for manipulating and creating SVals.
|
||||
GRTransferFuncs* TF;
|
||||
@ -583,6 +576,15 @@ inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond,
|
||||
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,
|
||||
|
@ -16,16 +16,19 @@
|
||||
#define LLVM_CLANG_ANALYSIS_GRWORKLIST
|
||||
|
||||
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
||||
class CFGBlock;
|
||||
class ExplodedNode;
|
||||
class ExplodedNodeImpl;
|
||||
|
||||
class GRWorkListUnit {
|
||||
ExplodedNode* Node;
|
||||
GRBlockCounter Counter;
|
||||
CFGBlock* Block;
|
||||
unsigned BlockIdx;
|
||||
unsigned BlockIdx; // This is the index of the next statement.
|
||||
|
||||
public:
|
||||
GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
|
||||
|
@ -77,6 +77,8 @@ class MemRegion : public llvm::FoldingSetNode {
|
||||
|
||||
const MemRegion *getBaseRegion() const;
|
||||
|
||||
const MemRegion *StripCasts() const;
|
||||
|
||||
bool hasStackStorage() const;
|
||||
|
||||
bool hasParametersStorage() const;
|
||||
|
@ -96,6 +96,8 @@ class SVal {
|
||||
return getRawKind() > UnknownKind;
|
||||
}
|
||||
|
||||
bool isConstant() const;
|
||||
|
||||
bool isZeroConstant() const;
|
||||
|
||||
/// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
|
||||
@ -434,7 +436,7 @@ class MemRegionVal : public Loc {
|
||||
return static_cast<MemRegion*>(Data);
|
||||
}
|
||||
|
||||
const MemRegion* getBaseRegion() const;
|
||||
const MemRegion* StripCasts() const;
|
||||
|
||||
template <typename REGION>
|
||||
const REGION* getRegionAs() const {
|
||||
|
@ -102,7 +102,8 @@ class StoreManager {
|
||||
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){
|
||||
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
||||
const MemRegion *region) {
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
@ -180,8 +181,7 @@ class StoreManager {
|
||||
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
|
||||
/// implicit casts that arise from loads from regions that are reinterpreted
|
||||
/// as another region.
|
||||
SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state,
|
||||
const TypedRegion *R, QualType castTy);
|
||||
SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy);
|
||||
};
|
||||
|
||||
// FIXME: Do we still need this?
|
||||
|
@ -33,13 +33,10 @@ class ProgramPoint {
|
||||
BlockEntranceKind,
|
||||
BlockExitKind,
|
||||
PreStmtKind,
|
||||
// Keep the following together and in this order.
|
||||
PostStmtKind,
|
||||
PostLocationChecksSucceedKind,
|
||||
PostOutOfBoundsCheckFailedKind,
|
||||
PostNullCheckFailedKind,
|
||||
PostUndefLocationCheckFailedKind,
|
||||
PreLoadKind,
|
||||
PostLoadKind,
|
||||
PreStoreKind,
|
||||
PostStoreKind,
|
||||
PostPurgeDeadSymbolsKind,
|
||||
PostStmtCustomKind,
|
||||
@ -194,17 +191,6 @@ class PostStmt : public StmtPoint {
|
||||
}
|
||||
};
|
||||
|
||||
class PostLocationChecksSucceed : public PostStmt {
|
||||
public:
|
||||
PostLocationChecksSucceed(const Stmt* S, const LocationContext *L,
|
||||
const void *tag = 0)
|
||||
: PostStmt(S, PostLocationChecksSucceedKind, L, tag) {}
|
||||
|
||||
static bool classof(const ProgramPoint* Location) {
|
||||
return Location->getKind() == PostLocationChecksSucceedKind;
|
||||
}
|
||||
};
|
||||
|
||||
class PostStmtCustom : public PostStmt {
|
||||
public:
|
||||
PostStmtCustom(const Stmt* S,
|
||||
@ -226,36 +212,36 @@ class PostStmtCustom : public PostStmt {
|
||||
}
|
||||
};
|
||||
|
||||
class PostOutOfBoundsCheckFailed : public PostStmt {
|
||||
|
||||
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:
|
||||
PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L,
|
||||
const void *tag = 0)
|
||||
: PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {}
|
||||
|
||||
static bool classof(const ProgramPoint* Location) {
|
||||
return Location->getKind() == PostOutOfBoundsCheckFailedKind;
|
||||
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 PostUndefLocationCheckFailed : public PostStmt {
|
||||
class PreStore : public LocationCheck {
|
||||
public:
|
||||
PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L,
|
||||
const void *tag = 0)
|
||||
: PostStmt(S, PostUndefLocationCheckFailedKind, L, tag) {}
|
||||
|
||||
static bool classof(const ProgramPoint* Location) {
|
||||
return Location->getKind() == PostUndefLocationCheckFailedKind;
|
||||
}
|
||||
};
|
||||
|
||||
class PostNullCheckFailed : public PostStmt {
|
||||
public:
|
||||
PostNullCheckFailed(const Stmt* S, const LocationContext *L,
|
||||
const void *tag = 0)
|
||||
: PostStmt(S, PostNullCheckFailedKind, L, tag) {}
|
||||
|
||||
static bool classof(const ProgramPoint* Location) {
|
||||
return Location->getKind() == PostNullCheckFailedKind;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,9 @@ class Optional {
|
||||
} //end clang namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename T> struct simplify_type;
|
||||
|
||||
template <typename T>
|
||||
struct simplify_type<const ::clang::Optional<T> > {
|
||||
typedef const T* SimpleType;
|
||||
|
@ -22,6 +22,9 @@ namespace clang {
|
||||
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:
|
||||
|
@ -32,6 +32,7 @@ namespace clang {
|
||||
class IdentifierInfo;
|
||||
class LangOptions;
|
||||
class PartialDiagnostic;
|
||||
class Preprocessor;
|
||||
class SourceRange;
|
||||
|
||||
// Import the diagnostic enums themselves.
|
||||
@ -105,6 +106,10 @@ class CodeModificationHint {
|
||||
/// modification is known.
|
||||
CodeModificationHint() : 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 CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
|
||||
@ -382,6 +387,7 @@ class Diagnostic {
|
||||
/// @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 Clear out the current diagnostic.
|
||||
void Clear() { CurDiagID = ~0U; }
|
||||
@ -586,6 +592,9 @@ class DiagnosticBuilder {
|
||||
}
|
||||
|
||||
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
|
||||
if (Hint.isNull())
|
||||
return;
|
||||
|
||||
assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
|
||||
"Too many code modification hints!");
|
||||
if (DiagObj)
|
||||
@ -664,6 +673,9 @@ inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
|
||||
CurDiagID = DiagID;
|
||||
return DiagnosticBuilder(this);
|
||||
}
|
||||
inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
|
||||
return Report(FullSourceLoc(), DiagID);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DiagnosticInfo
|
||||
@ -780,7 +792,8 @@ class DiagnosticClient {
|
||||
/// \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) {}
|
||||
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
|
||||
|
@ -52,4 +52,11 @@ def warn_integer_too_large_for_signed : Warning<
|
||||
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_abi : Error<"unknown target ABI '%0'">;
|
||||
def err_target_invalid_feature : Error<"invalid target feature '%0'">;
|
||||
|
||||
}
|
||||
|
@ -9,19 +9,33 @@
|
||||
|
||||
let Component = "Frontend" in {
|
||||
|
||||
def err_fe_unknown_triple : Error<
|
||||
"unknown target triple '%0', please use -triple or -arch">;
|
||||
def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
|
||||
def err_fe_error_opening : Error<"error opening '%0': %1">;
|
||||
def err_fe_error_reading : Error<"error reading '%0'">;
|
||||
def err_fe_error_reading_stdin : Error<"error reading stdin">;
|
||||
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
|
||||
def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
|
||||
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
|
||||
def err_fe_invalid_code_complete_file
|
||||
def err_fe_invalid_code_complete_file
|
||||
: Error<"cannot locate code-completion file %0">, DefaultFatal;
|
||||
def err_fe_dependency_file_requires_MT : Error<
|
||||
"-dependency-file requires at least one -MT option">;
|
||||
def 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_verify_bogus_characters : Error<
|
||||
"bogus characters before '{{' in expected string">;
|
||||
def err_verify_missing_start : Error<
|
||||
"cannot find start ('{{') of expected string">;
|
||||
def err_verify_missing_end : Error<
|
||||
"cannot find end ('}}') of expected string">;
|
||||
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<
|
||||
@ -162,6 +176,9 @@ def warn_pch_access_control : Error<
|
||||
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;
|
||||
|
@ -28,7 +28,7 @@ def : DiagGroup<"cast-align">;
|
||||
def : DiagGroup<"cast-qual">;
|
||||
def : DiagGroup<"char-align">;
|
||||
def Comment : DiagGroup<"comment">;
|
||||
def : DiagGroup<"conversion">;
|
||||
def : DiagGroup<"ctor-dtor-privacy">;
|
||||
def : DiagGroup<"declaration-after-statement">;
|
||||
def : DiagGroup<"disabled-optimization">;
|
||||
def : DiagGroup<"discard-qual">;
|
||||
@ -40,6 +40,7 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">;
|
||||
def FormatZeroLength : DiagGroup<"format-zero-length">;
|
||||
|
||||
def FourByteMultiChar : DiagGroup<"four-char-constants">;
|
||||
def : DiagGroup<"idiomatic-parentheses">;
|
||||
def : DiagGroup<"import">;
|
||||
def : DiagGroup<"init-self">;
|
||||
def : DiagGroup<"inline">;
|
||||
@ -58,19 +59,21 @@ def MismatchedTags : DiagGroup<"mismatched-tags">;
|
||||
def : 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 Parentheses : DiagGroup<"parentheses">;
|
||||
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 : DiagGroup<"shadow">;
|
||||
def : DiagGroup<"shorten-64-to-32">;
|
||||
def : DiagGroup<"sign-compare">;
|
||||
def SignCompare : DiagGroup<"sign-compare">;
|
||||
def : DiagGroup<"synth">;
|
||||
|
||||
// Preprocessor warnings.
|
||||
def : DiagGroup<"builtin-macro-redefined">;
|
||||
@ -114,6 +117,14 @@ 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">]>;
|
||||
|
||||
def Unused : DiagGroup<"unused",
|
||||
[UnusedArgument, UnusedFunction, UnusedLabel,
|
||||
@ -127,8 +138,9 @@ def FormatY2K : DiagGroup<"format-y2k", [Format]>;
|
||||
def Format2 : DiagGroup<"format=2",
|
||||
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
|
||||
|
||||
|
||||
def Extra : DiagGroup<"extra", [
|
||||
SemiBeforeMethodBody,
|
||||
SignCompare,
|
||||
UnusedParameter
|
||||
]>;
|
||||
|
||||
@ -158,3 +170,7 @@ def : DiagGroup<"all", [Most, Parentheses]>;
|
||||
def : DiagGroup<"", [Extra]>; // -W = -Wextra
|
||||
def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens
|
||||
|
||||
// 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]>;
|
||||
|
@ -89,6 +89,14 @@ 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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -201,9 +201,9 @@ def warn_expected_implementation : Warning<
|
||||
"@end must appear in an @implementation context">;
|
||||
def error_property_ivar_decl : Error<
|
||||
"property synthesize requires specification of an ivar">;
|
||||
def warn_semicolon_before_method_nody : Warning<
|
||||
def warn_semicolon_before_method_body : Warning<
|
||||
"semicolon before method body is ignored">,
|
||||
InGroup<DiagGroup<"semicolon-before-method-body">>;
|
||||
InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore;
|
||||
|
||||
def err_expected_field_designator : Error<
|
||||
"expected a field designator, such as '.field = 4'">;
|
||||
@ -230,7 +230,7 @@ def ext_ellipsis_exception_spec : 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' in class not allowed">;
|
||||
"'using namespace' is not allowed in classes">;
|
||||
def err_ident_in_pseudo_dtor_not_a_type : Error<
|
||||
"identifier %0 in pseudo-destructor expression does not name a type">;
|
||||
|
||||
@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error<
|
||||
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">;
|
||||
|
@ -103,6 +103,8 @@ 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_a_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<
|
||||
@ -115,6 +117,8 @@ 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 err_invalid_thread : Error<
|
||||
"'__thread' is only allowed on variable declarations">;
|
||||
@ -251,6 +255,7 @@ def warn_accessor_property_type_mismatch : Warning<
|
||||
def note_declared_at : Note<"declared at">;
|
||||
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<
|
||||
@ -269,6 +274,9 @@ def warn_property_attr_mismatch : Warning<
|
||||
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<
|
||||
"property declaration in continuation class of %0 is to change a 'readonly' "
|
||||
"property to 'readwrite'">;
|
||||
@ -397,7 +405,9 @@ 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">;
|
||||
|
||||
// C++ class members
|
||||
def err_storageclass_invalid_for_member : Error<
|
||||
"storage class specified for a member declaration">;
|
||||
@ -430,9 +440,15 @@ def err_implicit_object_parameter_init : Error<
|
||||
"cannot initialize object parameter of type %0 with an expression "
|
||||
"of type %1">;
|
||||
|
||||
def err_missing_default_constructor : Error<
|
||||
"default constructor for %1 is missing in initialization of "
|
||||
"%select{base class|member}0">;
|
||||
def note_field_decl : Note<"member is declared here">;
|
||||
def note_previous_class_decl : Note<
|
||||
"%0 declared here">;
|
||||
def note_ctor_synthesized_at : Note<
|
||||
"implicit default constructor for %0 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">;
|
||||
@ -632,6 +648,25 @@ def err_cconv_knr : Error<
|
||||
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_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<
|
||||
@ -744,27 +779,18 @@ 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 note_field_decl : Note<"member is declared here">;
|
||||
def err_defining_default_ctor : Error<
|
||||
"cannot define the implicit default constructor for %0, because %select{base class|member's type}1 "
|
||||
"%2 does not have any default constructor">;
|
||||
def note_previous_class_decl : Note<
|
||||
"%0 declared here">;
|
||||
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_unintialized_member : Error<
|
||||
"cannot define the implicit default constructor for %0, because "
|
||||
"%select{reference|const}1 member %2 cannot be default-initialized">;
|
||||
def err_null_intialized_reference_member : Error<
|
||||
"cannot initialize the member to null in default constructor because "
|
||||
"reference member %0 cannot be null-initialized">;
|
||||
def err_unintialized_member_in_ctor : Error<
|
||||
"constructor for %0 must explicitly initialize the "
|
||||
"%select{reference|const}1 member %2 ">;
|
||||
"%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">;
|
||||
@ -993,6 +1019,9 @@ def err_template_spec_friend : Error<
|
||||
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<
|
||||
@ -1083,6 +1112,12 @@ def note_function_template_deduction_instantiation_here : Note<
|
||||
def note_partial_spec_deduct_instantiation_here : Note<
|
||||
"during template argument deduction for class template partial "
|
||||
"specialization %0, here">;
|
||||
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 err_field_instantiates_to_function : Error<
|
||||
"data member instantiated with function type %0">;
|
||||
def err_nested_name_spec_non_tag : Error<
|
||||
@ -1447,8 +1482,9 @@ def err_typecheck_member_reference_type : Error<
|
||||
"cannot refer to type member %0 with '%select{.|->}1'">;
|
||||
def err_typecheck_member_reference_unknown : Error<
|
||||
"cannot refer to member %0 with '%select{.|->}1'">;
|
||||
def note_member_reference_needs_call : Note<
|
||||
"perhaps you meant to call this function with '()'?">;
|
||||
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;
|
||||
|
||||
@ -1488,6 +1524,9 @@ 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_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
|
||||
def err_typecheck_sclass_fscope : Error<
|
||||
@ -1539,10 +1578,10 @@ 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<DiagGroup<"sign-compare">>;
|
||||
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
|
||||
def warn_mixed_sign_conditional : Warning<
|
||||
"operands of ? are integers of different signs: %0 and %1">,
|
||||
InGroup<DiagGroup<"sign-compare">>;
|
||||
InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
|
||||
|
||||
def err_invalid_this_use : Error<
|
||||
"invalid use of 'this' outside of a nonstatic member function">;
|
||||
@ -1707,6 +1746,10 @@ 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_delete_member_function_declared_here : Note<
|
||||
"%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">;
|
||||
@ -1786,9 +1829,13 @@ def err_incomplete_object_call : Error<
|
||||
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 warn_value_always_zero : Warning<"%0 is always zero in this context">;
|
||||
def warn_value_always_false : Warning<"%0 is always false in this context">;
|
||||
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).
|
||||
// FIXME: %2 is an english string here.
|
||||
@ -1816,6 +1863,8 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn<
|
||||
"incompatible pointer types %2 %1, expected %0">;
|
||||
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
|
||||
"%2 %1 discards qualifiers, expected %0">;
|
||||
def ext_nested_pointer_qualifier_mismatch : ExtWarn<
|
||||
"%2, %0 and %1 have different qualifiers in nested pointer types">;
|
||||
def warn_incompatible_vectors : Warning<
|
||||
"incompatible vector types %2 %1, expected %0">,
|
||||
InGroup<VectorConversions>, DefaultIgnore;
|
||||
@ -2086,6 +2135,10 @@ def err_operator_overload_needs_class_or_enum : Error<
|
||||
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_new_param_type : Error<
|
||||
"%0 takes type size_t (%1) as first parameter">;
|
||||
def err_operator_new_result_type : Error<
|
||||
"%0 must return type %1">;
|
||||
def err_operator_overload_default_arg : Error<
|
||||
"parameter of overloaded %0 cannot have a default argument">;
|
||||
def err_operator_overload_must_be : Error<
|
||||
@ -2328,7 +2381,7 @@ 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_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<
|
||||
|
@ -55,6 +55,7 @@ class LangOptions {
|
||||
unsigned POSIXThreads : 1; // Compiling with POSIX thread support
|
||||
// (-pthread)
|
||||
unsigned Blocks : 1; // block extension to C
|
||||
unsigned BlockIntrospection: 1; // block have ObjC type encodings.
|
||||
unsigned EmitAllDecls : 1; // Emit all declarations, even if
|
||||
// they are unused.
|
||||
unsigned MathErrno : 1; // Math functions must respect errno
|
||||
@ -83,6 +84,7 @@ class LangOptions {
|
||||
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.
|
||||
|
||||
@ -125,7 +127,8 @@ class LangOptions {
|
||||
ObjCConstantStringClass = 0;
|
||||
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
|
||||
CXXOperatorNames = PascalStrings = WritableStrings = 0;
|
||||
Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
|
||||
Exceptions = Freestanding = NoBuiltin = 0;
|
||||
NeXTRuntime = 1;
|
||||
Rtti = 1;
|
||||
LaxVectorConversions = 1;
|
||||
HeinousExtensions = 0;
|
||||
@ -137,6 +140,7 @@ class LangOptions {
|
||||
ThreadsafeStatics = 0;
|
||||
POSIXThreads = 0;
|
||||
Blocks = 0;
|
||||
BlockIntrospection = 0;
|
||||
EmitAllDecls = 0;
|
||||
MathErrno = 1;
|
||||
|
||||
@ -159,6 +163,7 @@ class LangOptions {
|
||||
NoInline = 0;
|
||||
|
||||
CharIsSigned = 1;
|
||||
ShortWChar = 0;
|
||||
|
||||
MainFileName = 0;
|
||||
}
|
||||
|
@ -9,12 +9,14 @@ 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)
|
||||
$(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen"
|
||||
$(Verb) -$(MKDIR) $(@D)
|
||||
$(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 $(wildcard Diagnostic*.td) $(TBLGEN)
|
||||
$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN)
|
||||
$(Echo) "Building Clang diagnostic groups with tblgen"
|
||||
$(Verb) -$(MKDIR) $(@D)
|
||||
$(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $<
|
||||
|
@ -28,11 +28,12 @@ class StringRef;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Diagnostic;
|
||||
class LangOptions;
|
||||
class SourceLocation;
|
||||
class SourceManager;
|
||||
class LangOptions;
|
||||
class TargetOptions;
|
||||
|
||||
namespace Builtin { struct Info; }
|
||||
|
||||
/// TargetInfo - This class exposes information about the current target.
|
||||
@ -44,16 +45,12 @@ class TargetInfo {
|
||||
// values are specified by the TargetInfo constructor.
|
||||
bool TLSSupported;
|
||||
unsigned char PointerWidth, PointerAlign;
|
||||
unsigned char WCharWidth, WCharAlign;
|
||||
unsigned char Char16Width, Char16Align;
|
||||
unsigned char Char32Width, Char32Align;
|
||||
unsigned char IntWidth, IntAlign;
|
||||
unsigned char FloatWidth, FloatAlign;
|
||||
unsigned char DoubleWidth, DoubleAlign;
|
||||
unsigned char LongDoubleWidth, LongDoubleAlign;
|
||||
unsigned char LongWidth, LongAlign;
|
||||
unsigned char LongLongWidth, LongLongAlign;
|
||||
unsigned char IntMaxTWidth;
|
||||
const char *DescriptionString;
|
||||
const char *UserLabelPrefix;
|
||||
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
|
||||
@ -63,9 +60,9 @@ class TargetInfo {
|
||||
TargetInfo(const std::string &T);
|
||||
|
||||
public:
|
||||
/// CreateTargetInfo - Return the target info object for the specified target
|
||||
/// triple.
|
||||
static TargetInfo* CreateTargetInfo(const std::string &Triple);
|
||||
/// CreateTargetInfo - Construct a target for the given options.
|
||||
static TargetInfo* CreateTargetInfo(Diagnostic &Diags,
|
||||
const TargetOptions &Opts);
|
||||
|
||||
virtual ~TargetInfo();
|
||||
|
||||
@ -103,6 +100,10 @@ class TargetInfo {
|
||||
/// 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;
|
||||
@ -146,18 +147,18 @@ class TargetInfo {
|
||||
|
||||
/// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
|
||||
/// bits.
|
||||
unsigned getWCharWidth() const { return WCharWidth; }
|
||||
unsigned getWCharAlign() const { return WCharAlign; }
|
||||
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 Char16Width; }
|
||||
unsigned getChar16Align() const { return Char16Align; }
|
||||
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 Char32Width; }
|
||||
unsigned getChar32Align() const { return Char32Align; }
|
||||
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; }
|
||||
@ -180,7 +181,7 @@ class TargetInfo {
|
||||
/// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
|
||||
/// target, in bits.
|
||||
unsigned getIntMaxTWidth() const {
|
||||
return IntMaxTWidth;
|
||||
return getTypeWidth(IntMaxType);
|
||||
}
|
||||
|
||||
/// getUserLabelPrefix - This returns the default value of the
|
||||
@ -341,10 +342,10 @@ class TargetInfo {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {}
|
||||
/// 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
|
||||
@ -375,9 +376,10 @@ class TargetInfo {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// HandleTargetOptions - Perform initialization based on the user
|
||||
/// configured set of features.
|
||||
virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) {
|
||||
/// 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.
|
||||
virtual void HandleTargetFeatures(const std::vector<std::string> &Features) {
|
||||
}
|
||||
|
||||
// getRegParmMax - Returns maximal number of args passed in registers.
|
||||
|
39
include/clang/Basic/TargetOptions.h
Normal file
39
include/clang/Basic/TargetOptions.h
Normal file
@ -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
|
75
include/clang/CodeGen/CodeGenOptions.h
Normal file
75
include/clang/CodeGen/CodeGenOptions.h
Normal file
@ -0,0 +1,75 @@
|
||||
//===--- 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>
|
||||
#include <vector>
|
||||
|
||||
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.
|
||||
};
|
||||
|
||||
unsigned DebugInfo : 1; /// Should generate deubg info (-g).
|
||||
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 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 OptimizationLevel : 3; /// The -O[0-4] option specified.
|
||||
unsigned OptimizeSize : 1; /// If -Os is specified.
|
||||
unsigned SimplifyLibCalls : 1; /// Should standard library calls be treated
|
||||
/// specially.
|
||||
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 VerifyModule : 1; /// Control whether the module should be run
|
||||
/// through the LLVM Verifier.
|
||||
|
||||
/// Inlining - The kind of inlining to perform.
|
||||
InliningMethod Inlining;
|
||||
|
||||
public:
|
||||
CodeGenOptions() {
|
||||
OptimizationLevel = 0;
|
||||
OptimizeSize = 0;
|
||||
DebugInfo = 0;
|
||||
UnitAtATime = 1;
|
||||
SimplifyLibCalls = UnrollLoops = 0;
|
||||
VerifyModule = 1;
|
||||
TimePasses = 0;
|
||||
NoCommon = 0;
|
||||
Inlining = NoInlining;
|
||||
DisableRedZone = 0;
|
||||
NoImplicitFloat = 0;
|
||||
MergeAllConstants = 1;
|
||||
DisableLLVMOpts = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
@ -25,7 +25,7 @@ namespace llvm {
|
||||
namespace clang {
|
||||
class Diagnostic;
|
||||
class LangOptions;
|
||||
class CompileOptions;
|
||||
class CodeGenOptions;
|
||||
|
||||
class CodeGenerator : public ASTConsumer {
|
||||
public:
|
||||
@ -35,7 +35,7 @@ namespace clang {
|
||||
|
||||
CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
|
||||
const std::string &ModuleName,
|
||||
const CompileOptions &CO,
|
||||
const CodeGenOptions &CGO,
|
||||
llvm::LLVMContext& C);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ class Driver {
|
||||
public:
|
||||
// Diag - Forwarding function for diagnostics.
|
||||
DiagnosticBuilder Diag(unsigned DiagID) const {
|
||||
return Diags.Report(FullSourceLoc(), DiagID);
|
||||
return Diags.Report(DiagID);
|
||||
}
|
||||
|
||||
// FIXME: Privatize once interface is stable.
|
||||
|
@ -368,6 +368,7 @@ OPTION("-fastcp", fastcp, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fastf", fastf, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fast", fast, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fasynchronous-unwind-tables", fasynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fblock-introspection", fblock_introspection, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fblocks", fblocks, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fbootclasspath=", fbootclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fbuiltin-strcat", fbuiltin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
@ -430,6 +431,7 @@ OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0
|
||||
OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-ms-extensions", fno_ms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
@ -448,7 +450,6 @@ OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fobjc-sender-dependent-dispatch", fobjc_sender_dependent_dispatch, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fopenmp", fopenmp, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
@ -463,6 +464,7 @@ OPTION("-fprofile-arcs", fprofile_arcs, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
|
||||
OPTION("-frtti", frtti, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fshort-wchar", fshort_wchar, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
|
@ -90,6 +90,17 @@ class ToolChain {
|
||||
/// default.
|
||||
virtual bool IsMathErrnoDefault() const = 0;
|
||||
|
||||
/// IsBlocksDefault - Does this tool chain enable -fblocks by default.
|
||||
virtual bool IsBlocksDefault() const { return false; }
|
||||
|
||||
/// IsObjCNonFragileABIDefault - Does this tool chain set
|
||||
/// -fobjc-nonfragile-abi by default.
|
||||
virtual bool IsObjCNonFragileABIDefault() 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;
|
||||
|
@ -62,6 +62,9 @@ namespace types {
|
||||
/// 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);
|
||||
|
@ -25,11 +25,12 @@ namespace llvm {
|
||||
namespace clang {
|
||||
|
||||
class ASTConsumer;
|
||||
class CodeGenOptions;
|
||||
class Diagnostic;
|
||||
class FileManager;
|
||||
class Preprocessor;
|
||||
class CompileOptions;
|
||||
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
|
||||
@ -69,7 +70,7 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile,
|
||||
bool SilenceRewriteMacroWarning);
|
||||
|
||||
// LLVM code generator: uses the code generation backend to generate LLVM
|
||||
// assembly. This runs optimizations depending on the CompileOptions
|
||||
// assembly. This runs optimizations depending on the CodeGenOptions
|
||||
// parameter. The output depends on the Action parameter.
|
||||
enum BackendAction {
|
||||
Backend_EmitAssembly, // Emit native assembly
|
||||
@ -80,7 +81,8 @@ enum BackendAction {
|
||||
ASTConsumer *CreateBackendConsumer(BackendAction Action,
|
||||
Diagnostic &Diags,
|
||||
const LangOptions &Features,
|
||||
const CompileOptions &CompileOpts,
|
||||
const CodeGenOptions &CodeGenOpts,
|
||||
const TargetOptions &TargetOpts,
|
||||
const std::string &ModuleID,
|
||||
llvm::raw_ostream *OS,
|
||||
llvm::LLVMContext& C);
|
||||
|
@ -48,6 +48,9 @@ ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars",
|
||||
ANALYSIS(CheckerCFRef, "checker-cfref",
|
||||
"Run the [Core] Foundation reference count checker", Code)
|
||||
|
||||
ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer",
|
||||
"Warn about unintended use of sizeof() on pointer expressions", Code)
|
||||
|
||||
ANALYSIS(InlineCall, "inline-call",
|
||||
"Experimental transfer function inling callees when its definition"
|
||||
" is available.", TranslationUnit)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===--- AnalysisConsumer.h - Front-end hooks for the analysis engine------===//
|
||||
//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -12,6 +12,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H
|
||||
#define LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -50,19 +53,37 @@ enum AnalysisDiagClients {
|
||||
NUM_ANALYSIS_DIAG_CLIENTS
|
||||
};
|
||||
|
||||
struct AnalyzerOptions {
|
||||
class AnalyzerOptions {
|
||||
public:
|
||||
std::vector<Analyses> AnalysisList;
|
||||
AnalysisStores AnalysisStoreOpt;
|
||||
AnalysisConstraints AnalysisConstraintsOpt;
|
||||
AnalysisDiagClients AnalysisDiagOpt;
|
||||
bool VisualizeEGDot;
|
||||
bool VisualizeEGUbi;
|
||||
bool AnalyzeAll;
|
||||
bool AnalyzerDisplayProgress;
|
||||
bool PurgeDead;
|
||||
bool EagerlyAssume;
|
||||
std::string AnalyzeSpecificFunction;
|
||||
bool TrimGraph;
|
||||
unsigned AnalyzeAll : 1;
|
||||
unsigned AnalyzerDisplayProgress : 1;
|
||||
unsigned EagerlyAssume : 1;
|
||||
unsigned PurgeDead : 1;
|
||||
unsigned TrimGraph : 1;
|
||||
unsigned VisualizeEGDot : 1;
|
||||
unsigned VisualizeEGUbi : 1;
|
||||
unsigned EnableExperimentalChecks : 1;
|
||||
unsigned EnableExperimentalInternalChecks : 1;
|
||||
public:
|
||||
AnalyzerOptions() {
|
||||
AnalysisStoreOpt = BasicStoreModel;
|
||||
AnalysisConstraintsOpt = RangeConstraintsModel;
|
||||
AnalysisDiagOpt = PD_HTML;
|
||||
AnalyzeAll = 0;
|
||||
AnalyzerDisplayProgress = 0;
|
||||
EagerlyAssume = 0;
|
||||
PurgeDead = 0;
|
||||
TrimGraph = 0;
|
||||
VisualizeEGDot = 0;
|
||||
VisualizeEGUbi = 0;
|
||||
EnableExperimentalChecks = 0;
|
||||
EnableExperimentalInternalChecks = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
|
||||
@ -73,3 +94,5 @@ ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
|
||||
const AnalyzerOptions& Opts);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
58
include/clang/Frontend/ChainedDiagnosticClient.h
Normal file
58
include/clang/Frontend/ChainedDiagnosticClient.h
Normal file
@ -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
|
@ -1,3 +1,4 @@
|
||||
|
||||
//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@ -37,7 +38,7 @@ namespace llvm {
|
||||
class parser<clang::ParsedSourceLocation>
|
||||
: public basic_parser<clang::ParsedSourceLocation> {
|
||||
public:
|
||||
bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
|
||||
inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
|
||||
clang::ParsedSourceLocation &Val);
|
||||
};
|
||||
|
||||
|
523
include/clang/Frontend/CompilerInstance.h
Normal file
523
include/clang/Frontend/CompilerInstance.h
Normal file
@ -0,0 +1,523 @@
|
||||
//===-- 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/StringRef.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class raw_ostream;
|
||||
class raw_fd_ostream;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class ASTConsumer;
|
||||
class CodeCompleteConsumer;
|
||||
class Diagnostic;
|
||||
class DiagnosticClient;
|
||||
class ExternalASTSource;
|
||||
class FileManager;
|
||||
class Preprocessor;
|
||||
class Source;
|
||||
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::LLVMContext *LLVMContext;
|
||||
bool OwnsLLVMContext;
|
||||
|
||||
/// The options used in this compiler instance.
|
||||
CompilerInvocation Invocation;
|
||||
|
||||
/// The diagnostics engine instance.
|
||||
llvm::OwningPtr<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 list of active output files.
|
||||
std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
|
||||
|
||||
public:
|
||||
/// Create a new compiler instance with the given LLVM context, optionally
|
||||
/// taking ownership of it.
|
||||
CompilerInstance(llvm::LLVMContext *_LLVMContext = 0,
|
||||
bool _OwnsLLVMContext = true);
|
||||
~CompilerInstance();
|
||||
|
||||
/// @name LLVM Context
|
||||
/// {
|
||||
|
||||
bool hasLLVMContext() const { return LLVMContext != 0; }
|
||||
|
||||
llvm::LLVMContext &getLLVMContext() const {
|
||||
assert(LLVMContext && "Compiler instance has no LLVM context!");
|
||||
return *LLVMContext;
|
||||
}
|
||||
|
||||
/// setLLVMContext - Replace the current LLVM context and take ownership of
|
||||
/// \arg Value.
|
||||
void setLLVMContext(llvm::LLVMContext *Value, bool TakeOwnership = true) {
|
||||
LLVMContext = Value;
|
||||
OwnsLLVMContext = TakeOwnership;
|
||||
}
|
||||
|
||||
/// }
|
||||
/// @name Compiler Invocation and Options
|
||||
/// {
|
||||
|
||||
CompilerInvocation &getInvocation() { return Invocation; }
|
||||
const CompilerInvocation &getInvocation() const { return Invocation; }
|
||||
void setInvocation(const CompilerInvocation &Value) { Invocation = 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;
|
||||
}
|
||||
|
||||
/// takeDiagnostics - Remove the current diagnostics engine and give ownership
|
||||
/// to the caller.
|
||||
Diagnostic *takeDiagnostics() { return Diagnostics.take(); }
|
||||
|
||||
/// setDiagnostics - Replace the current diagnostics engine; the compiler
|
||||
/// instance takes ownership of \arg Value.
|
||||
void setDiagnostics(Diagnostic *Value);
|
||||
|
||||
DiagnosticClient &getDiagnosticClient() const {
|
||||
assert(Target && "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 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 releaseing the returned Diagnostic's client
|
||||
/// eventually.
|
||||
///
|
||||
/// \return The new object on success, or null on failure.
|
||||
static 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 &,
|
||||
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,
|
||||
llvm::raw_ostream &OS);
|
||||
|
||||
/// Create the default output file (from the invocation's options) and add it
|
||||
/// to the list of tracked output files.
|
||||
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.
|
||||
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
|
150
include/clang/Frontend/CompilerInvocation.h
Normal file
150
include/clang/Frontend/CompilerInvocation.h
Normal file
@ -0,0 +1,150 @@
|
||||
//===-- 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 {
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// FIXME: Documenting error behavior.
|
||||
///
|
||||
/// \param Res [out] - The resulting invocation.
|
||||
/// \param Args - The input argument strings.
|
||||
static void CreateFromArgs(CompilerInvocation &Res,
|
||||
const llvm::SmallVectorImpl<llvm::StringRef> &Args);
|
||||
|
||||
/// 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
|
43
include/clang/Frontend/DependencyOutputOptions.h
Normal file
43
include/clang/Frontend/DependencyOutputOptions.h
Normal file
@ -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
|
@ -19,6 +19,10 @@ namespace clang {
|
||||
/// 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.
|
||||
@ -27,20 +31,36 @@ class DiagnosticOptions {
|
||||
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
|
||||
/// diagnostics.
|
||||
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
|
||||
unsigned VerifyDiagnostics; /// Check that diagnostics match the expected
|
||||
/// diagnostics, indicated by markers in the
|
||||
/// input source file.
|
||||
|
||||
/// 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() {
|
||||
ShowColumn = 1;
|
||||
ShowLocation = 1;
|
||||
ShowCarets = 1;
|
||||
ShowFixits = 1;
|
||||
ShowSourceRanges = 0;
|
||||
ShowOptionNames = 0;
|
||||
ShowColors = 0;
|
||||
IgnoreWarnings = 0;
|
||||
MessageLength = 0;
|
||||
NoRewriteMacros = 0;
|
||||
Pedantic = 0;
|
||||
PedanticErrors = 0;
|
||||
ShowCarets = 1;
|
||||
ShowColors = 0;
|
||||
ShowColumn = 1;
|
||||
ShowFixits = 1;
|
||||
ShowLocation = 1;
|
||||
ShowOptionNames = 0;
|
||||
ShowSourceRanges = 0;
|
||||
VerifyDiagnostics = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
215
include/clang/Frontend/FrontendAction.h
Normal file
215
include/clang/Frontend/FrontendAction.h
Normal file
@ -0,0 +1,215 @@
|
||||
//===-- 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 llvm {
|
||||
class Timer;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTUnit;
|
||||
class ASTConsumer;
|
||||
class CompilerInstance;
|
||||
|
||||
/// FrontendAction - Abstract base class for actions which can be performed by
|
||||
/// the frontend.
|
||||
class FrontendAction {
|
||||
std::string CurrentFile;
|
||||
llvm::OwningPtr<ASTUnit> CurrentASTUnit;
|
||||
CompilerInstance *Instance;
|
||||
llvm::Timer *CurrentTimer;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0);
|
||||
|
||||
/// @}
|
||||
/// @name Timing Utilities
|
||||
/// @{
|
||||
|
||||
llvm::Timer *getCurrentTimer() const {
|
||||
return CurrentTimer;
|
||||
}
|
||||
|
||||
void setCurrentTimer(llvm::Timer *Value) {
|
||||
CurrentTimer = Value;
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @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 actios.
|
||||
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
|
216
include/clang/Frontend/FrontendActions.h
Normal file
216
include/clang/Frontend/FrontendActions.h
Normal file
@ -0,0 +1,216 @@
|
||||
//===-- 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"
|
||||
|
||||
namespace clang {
|
||||
class FixItRewriter;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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 DumpRecordAction : public ASTFrontendAction {
|
||||
protected:
|
||||
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
|
||||
llvm::StringRef InFile);
|
||||
};
|
||||
|
||||
class FixItAction : public ASTFrontendAction {
|
||||
private:
|
||||
llvm::OwningPtr<FixItRewriter> Rewriter;
|
||||
|
||||
protected:
|
||||
|
||||
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 RewriteBlocksAction : 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; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Code Gen AST Actions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CodeGenAction : public ASTFrontendAction {
|
||||
private:
|
||||
unsigned Act;
|
||||
|
||||
protected:
|
||||
CodeGenAction(unsigned _Act);
|
||||
|
||||
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
|
||||
llvm::StringRef InFile);
|
||||
};
|
||||
|
||||
class EmitAssemblyAction : public CodeGenAction {
|
||||
public:
|
||||
EmitAssemblyAction();
|
||||
};
|
||||
|
||||
class EmitBCAction : public CodeGenAction {
|
||||
public:
|
||||
EmitBCAction();
|
||||
};
|
||||
|
||||
class EmitLLVMAction : public CodeGenAction {
|
||||
public:
|
||||
EmitLLVMAction();
|
||||
};
|
||||
|
||||
class EmitLLVMOnlyAction : public CodeGenAction {
|
||||
public:
|
||||
EmitLLVMOnlyAction();
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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
|
131
include/clang/Frontend/FrontendOptions.h
Normal file
131
include/clang/Frontend/FrontendOptions.h
Normal file
@ -0,0 +1,131 @@
|
||||
//===--- 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.
|
||||
DumpRawTokens, ///< Dump out raw tokens.
|
||||
DumpRecordLayouts, ///< Dump record layout information.
|
||||
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
|
||||
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.
|
||||
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.
|
||||
RewriteBlocks, ///< ObjC->C Rewriter for Blocks.
|
||||
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 EmptyInputOnly : 1; ///< Force input files to be treated
|
||||
/// as if they were empty, for timing
|
||||
/// the frontend startup.
|
||||
unsigned RelocatablePCH : 1; ///< When generating PCH files,
|
||||
/// instruct the PCH writer to create
|
||||
/// relocatable PCH files.
|
||||
unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
|
||||
/// results.
|
||||
unsigned ShowStats : 1; ///< Show frontend performance
|
||||
/// metrics and statistics.
|
||||
unsigned ShowTimers : 1; ///< Show timers for individual
|
||||
/// actions.
|
||||
|
||||
/// 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;
|
||||
|
||||
/// A list of locations to apply fix-its at.
|
||||
std::vector<ParsedSourceLocation> FixItLocations;
|
||||
|
||||
/// 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;
|
||||
|
||||
public:
|
||||
FrontendOptions() {
|
||||
DebugCodeCompletionPrinter = 0;
|
||||
DisableFree = 0;
|
||||
EmptyInputOnly = 0;
|
||||
ProgramAction = frontend::ParseSyntaxOnly;
|
||||
ActionName = "";
|
||||
RelocatablePCH = 0;
|
||||
ShowMacrosInCodeCompletion = 0;
|
||||
ShowStats = 0;
|
||||
ShowTimers = 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
|
23
include/clang/Frontend/FrontendPluginRegistry.h
Normal file
23
include/clang/Frontend/FrontendPluginRegistry.h
Normal file
@ -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
|
87
include/clang/Frontend/HeaderSearchOptions.h
Normal file
87
include/clang/Frontend/HeaderSearchOptions.h
Normal file
@ -0,0 +1,87 @@
|
||||
//===--- 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;
|
||||
|
||||
/// If non-empty, the path to the compiler builtin include directory, which
|
||||
/// will be searched following the user and environment includes.
|
||||
std::string BuiltinIncludePath;
|
||||
|
||||
/// Include the system standard include search directories.
|
||||
unsigned UseStandardIncludes : 1;
|
||||
|
||||
/// Whether header search information should be output as for -v.
|
||||
unsigned Verbose : 1;
|
||||
|
||||
public:
|
||||
HeaderSearchOptions(llvm::StringRef _Sysroot = "")
|
||||
: Sysroot(_Sysroot), UseStandardIncludes(true) {}
|
||||
|
||||
/// 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
|
@ -29,6 +29,7 @@
|
||||
#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>
|
||||
@ -78,7 +79,7 @@ class PCHReaderListener {
|
||||
/// \brief Receives the target triple.
|
||||
///
|
||||
/// \returns true to indicate the target triple is invalid or false otherwise.
|
||||
virtual bool ReadTargetTriple(const std::string &Triple) {
|
||||
virtual bool ReadTargetTriple(llvm::StringRef Triple) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -87,18 +88,18 @@ class PCHReaderListener {
|
||||
/// \param PCHPredef The start of the predefines buffer in the PCH
|
||||
/// file.
|
||||
///
|
||||
/// \param PCHPredefLen The length 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(const char *PCHPredef,
|
||||
unsigned PCHPredefLen,
|
||||
virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
|
||||
FileID PCHBufferID,
|
||||
llvm::StringRef OriginalFileName,
|
||||
std::string &SuggestedPredefines) {
|
||||
return false;
|
||||
}
|
||||
@ -123,10 +124,10 @@ class PCHValidator : public PCHReaderListener {
|
||||
: PP(PP), Reader(Reader), NumHeaderInfos(0) {}
|
||||
|
||||
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
|
||||
virtual bool ReadTargetTriple(const std::string &Triple);
|
||||
virtual bool ReadPredefinesBuffer(const char *PCHPredef,
|
||||
unsigned PCHPredefLen,
|
||||
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);
|
||||
virtual void ReadCounter(unsigned Value);
|
||||
@ -312,10 +313,13 @@ class PCHReader
|
||||
/// the PCH file.
|
||||
llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
|
||||
|
||||
/// \brief The original file name that was used to build the PCH
|
||||
/// file.
|
||||
/// \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;
|
||||
|
||||
@ -444,9 +448,7 @@ class PCHReader
|
||||
void MaybeAddSystemRootToFilename(std::string &Filename);
|
||||
|
||||
PCHReadResult ReadPCHBlock();
|
||||
bool CheckPredefinesBuffer(const char *PCHPredef,
|
||||
unsigned PCHPredefLen,
|
||||
FileID PCHBufferID);
|
||||
bool CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID);
|
||||
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
|
||||
PCHReadResult ReadSourceManagerBlock();
|
||||
PCHReadResult ReadSLocEntryRecord(unsigned ID);
|
||||
@ -625,13 +627,15 @@ class PCHReader
|
||||
|
||||
/// \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. FIXME: if this identifier names a macro, deserialize
|
||||
/// the macro.
|
||||
/// 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. FIXME: if this identifier names a macro,
|
||||
/// deserialize the macro.
|
||||
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.
|
||||
|
@ -52,7 +52,8 @@ struct UnsafeQualTypeDenseMapInfo {
|
||||
return QualType::getFromOpaquePtr((void*) 2);
|
||||
}
|
||||
static inline unsigned getHashValue(QualType T) {
|
||||
assert(!T.getFastQualifiers() && "hash invalid for types with fast quals");
|
||||
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);
|
||||
}
|
||||
|
57
include/clang/Frontend/PreprocessorOptions.h
Normal file
57
include/clang/Frontend/PreprocessorOptions.h
Normal file
@ -0,0 +1,57 @@
|
||||
//===--- 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 <vector>
|
||||
|
||||
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.
|
||||
|
||||
/// 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;
|
||||
|
||||
public:
|
||||
PreprocessorOptions() : UsePredefines(true) {}
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
37
include/clang/Frontend/PreprocessorOutputOptions.h
Normal file
37
include/clang/Frontend/PreprocessorOutputOptions.h
Normal file
@ -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
|
@ -34,12 +34,15 @@ class TextDiagnosticPrinter : public DiagnosticClient {
|
||||
|
||||
SourceLocation LastWarningLoc;
|
||||
FullSourceLoc LastLoc;
|
||||
bool LastCaretDiagnosticWasNote;
|
||||
unsigned LastCaretDiagnosticWasNote : 1;
|
||||
unsigned OwnsOutputStream : 1;
|
||||
|
||||
public:
|
||||
TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
|
||||
TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags,
|
||||
bool OwnsOutputStream = false);
|
||||
virtual ~TextDiagnosticPrinter();
|
||||
|
||||
void BeginSourceFile(const LangOptions &LO) {
|
||||
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) {
|
||||
LangOpts = &LO;
|
||||
}
|
||||
|
||||
|
@ -65,9 +65,9 @@
|
||||
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(isConstQualified(), "const") // boolean
|
||||
ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean
|
||||
ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean
|
||||
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
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===--- Utils.h - Misc utilities for the front-end------------------------===//
|
||||
//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,42 +14,57 @@
|
||||
#ifndef LLVM_CLANG_FRONTEND_UTILS_H
|
||||
#define LLVM_CLANG_FRONTEND_UTILS_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
class raw_ostream;
|
||||
class raw_fd_ostream;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class Preprocessor;
|
||||
class MinimalAction;
|
||||
class TargetInfo;
|
||||
class Diagnostic;
|
||||
class ASTConsumer;
|
||||
class IdentifierTable;
|
||||
class SourceManager;
|
||||
class LangOptions;
|
||||
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;
|
||||
|
||||
/// 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);
|
||||
|
||||
/// ProcessWarningOptions - Initialize the diagnostic client and process the
|
||||
/// warning options specified on the command line.
|
||||
bool ProcessWarningOptions(Diagnostic &Diags,
|
||||
std::vector<std::string> &Warnings,
|
||||
bool Pedantic, bool PedanticErrors,
|
||||
bool NoWarnings);
|
||||
|
||||
/// DoPrintPreprocessedInput - Implement -E -dM mode.
|
||||
void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream* OS);
|
||||
bool ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
|
||||
|
||||
/// DoPrintPreprocessedInput - Implement -E mode.
|
||||
void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
|
||||
bool EnableCommentOutput,
|
||||
bool EnableMacroCommentOutput,
|
||||
bool DisableLineMarkers,
|
||||
bool DumpDefines);
|
||||
const PreprocessorOutputOptions &Opts);
|
||||
|
||||
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
|
||||
void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS);
|
||||
@ -67,13 +82,12 @@ 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, llvm::raw_ostream *OS,
|
||||
std::vector<std::string> &Targets,
|
||||
bool IncludeSystemHeaders, bool PhonyTarget);
|
||||
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);
|
||||
void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
82
include/clang/Frontend/VerifyDiagnosticsClient.h
Normal file
82
include/clang/Frontend/VerifyDiagnosticsClient.h
Normal file
@ -0,0 +1,82 @@
|
||||
//===-- 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 SourceMgr;
|
||||
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}"
|
||||
/// 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}}
|
||||
///
|
||||
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
|
@ -119,8 +119,7 @@ class PTHManager : public IdentifierInfoLookup {
|
||||
|
||||
/// 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 = 0,
|
||||
Diagnostic::Level failureLevel=Diagnostic::Warning);
|
||||
static PTHManager *Create(const std::string& file, Diagnostic &Diags);
|
||||
|
||||
void setPreprocessor(Preprocessor *pp) { PP = pp; }
|
||||
|
||||
|
@ -51,7 +51,7 @@ class DirectoryLookup;
|
||||
class Preprocessor {
|
||||
Diagnostic *Diags;
|
||||
LangOptions Features;
|
||||
TargetInfo &Target;
|
||||
const TargetInfo &Target;
|
||||
FileManager &FileMgr;
|
||||
SourceManager &SourceMgr;
|
||||
ScratchBuffer *ScratchBuf;
|
||||
@ -94,6 +94,9 @@ class Preprocessor {
|
||||
bool DisableMacroExpansion : 1; // True if macro expansion is disabled.
|
||||
bool InMacroArgs : 1; // True if parsing fn macro invocation args.
|
||||
|
||||
/// Whether the preprocessor owns the header search object.
|
||||
bool OwnsHeaderSearch : 1;
|
||||
|
||||
/// Identifiers - This is mapping/lookup information for all identifiers in
|
||||
/// the program, including program keywords.
|
||||
mutable IdentifierTable Identifiers;
|
||||
@ -207,9 +210,11 @@ class Preprocessor {
|
||||
std::vector<CachedTokensTy::size_type> BacktrackPositions;
|
||||
|
||||
public:
|
||||
Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
|
||||
Preprocessor(Diagnostic &diags, const LangOptions &opts,
|
||||
const TargetInfo &target,
|
||||
SourceManager &SM, HeaderSearch &Headers,
|
||||
IdentifierInfoLookup *IILookup = 0);
|
||||
IdentifierInfoLookup *IILookup = 0,
|
||||
bool OwnsHeaderSearch = false);
|
||||
|
||||
~Preprocessor();
|
||||
|
||||
@ -217,7 +222,7 @@ class Preprocessor {
|
||||
void setDiagnostics(Diagnostic &D) { Diags = &D; }
|
||||
|
||||
const LangOptions &getLangOptions() const { return Features; }
|
||||
TargetInfo &getTargetInfo() const { return Target; }
|
||||
const TargetInfo &getTargetInfo() const { return Target; }
|
||||
FileManager &getFileManager() const { return FileMgr; }
|
||||
SourceManager &getSourceManager() const { return SourceMgr; }
|
||||
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
|
||||
@ -498,6 +503,15 @@ class Preprocessor {
|
||||
/// UCNs, etc.
|
||||
std::string getSpelling(const Token &Tok) 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);
|
||||
|
||||
/// 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
|
||||
|
@ -248,69 +248,6 @@ struct PPConditionalInfo {
|
||||
bool FoundElse;
|
||||
};
|
||||
|
||||
/// TemplateIdAnnotation - Information about a template-id annotation
|
||||
/// token, which contains the template declaration, template
|
||||
/// arguments, whether those template arguments were types or
|
||||
/// expressions, 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::DeclTy*.
|
||||
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
|
||||
void **getTemplateArgs() { return (void **)(this + 1); }
|
||||
|
||||
/// \brief Retrieves a pointer to the array of template argument
|
||||
/// locations.
|
||||
SourceLocation *getTemplateArgLocations() {
|
||||
return (SourceLocation *)(getTemplateArgs() + NumArgs);
|
||||
}
|
||||
|
||||
/// \brief Retrieves a pointer to the array of flags that states
|
||||
/// whether the template arguments are types.
|
||||
bool *getTemplateArgIsType() {
|
||||
return (bool *)(getTemplateArgLocations() + NumArgs);
|
||||
}
|
||||
|
||||
static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
|
||||
TemplateIdAnnotation *TemplateId
|
||||
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
|
||||
sizeof(void*) * NumArgs +
|
||||
sizeof(SourceLocation) * NumArgs +
|
||||
sizeof(bool) * NumArgs);
|
||||
TemplateId->NumArgs = NumArgs;
|
||||
return TemplateId;
|
||||
}
|
||||
|
||||
void Destroy() { free(this); }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -1203,6 +1203,8 @@ class Action : public ActionBase {
|
||||
/// '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,
|
||||
@ -1210,7 +1212,8 @@ class Action : public ActionBase {
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
AttributeList *AttrList,
|
||||
bool IsTypeName);
|
||||
bool IsTypeName,
|
||||
SourceLocation TypenameLoc);
|
||||
|
||||
/// ActOnParamDefaultArgument - Parse default argument for function parameter
|
||||
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
|
||||
@ -1577,7 +1580,7 @@ class Action : public ActionBase {
|
||||
/// parameter.
|
||||
virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
|
||||
SourceLocation EqualLoc,
|
||||
ExprArg Default) {
|
||||
const ParsedTemplateArgument &Default) {
|
||||
}
|
||||
|
||||
/// ActOnTemplateParameterList - Called when a complete template
|
||||
@ -1632,7 +1635,6 @@ class Action : public ActionBase {
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return TypeResult();
|
||||
};
|
||||
@ -1737,7 +1739,6 @@ class Action : public ActionBase {
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc,
|
||||
AttributeList *Attr,
|
||||
MultiTemplateParamsArg TemplateParameterLists) {
|
||||
@ -1817,7 +1818,6 @@ class Action : public ActionBase {
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc,
|
||||
AttributeList *Attr) {
|
||||
return DeclResult();
|
||||
@ -2105,6 +2105,7 @@ class Action : public ActionBase {
|
||||
virtual DeclPtrTy ActOnForwardClassDeclaration(
|
||||
SourceLocation AtClassLoc,
|
||||
IdentifierInfo **IdentList,
|
||||
SourceLocation *IdentLocs,
|
||||
unsigned NumElts) {
|
||||
return DeclPtrTy();
|
||||
}
|
||||
@ -2329,6 +2330,47 @@ class Action : public ActionBase {
|
||||
///
|
||||
/// \param S the scope in which the operator keyword occurs.
|
||||
virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { }
|
||||
|
||||
/// \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.
|
||||
///
|
||||
/// \param S the scope in which the message expression occurs.
|
||||
/// \param FName the factory name.
|
||||
/// \param FNameLoc the source location of the factory name.
|
||||
virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
|
||||
SourceLocation FNameLoc){ }
|
||||
|
||||
/// \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.
|
||||
///
|
||||
/// \param S the scope in which the operator keyword occurs.
|
||||
/// \param Receiver an expression for the receiver of the message.
|
||||
virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { }
|
||||
|
||||
/// \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) { }
|
||||
//@}
|
||||
};
|
||||
|
||||
@ -2398,6 +2440,7 @@ class MinimalAction : public Action {
|
||||
|
||||
virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
||||
IdentifierInfo **IdentList,
|
||||
SourceLocation *SLocs,
|
||||
unsigned NumElts);
|
||||
|
||||
virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc,
|
||||
|
@ -57,6 +57,7 @@ class AttributeList {
|
||||
AT_analyzer_noreturn,
|
||||
AT_annotate,
|
||||
AT_blocks,
|
||||
AT_cdecl,
|
||||
AT_cleanup,
|
||||
AT_const,
|
||||
AT_constructor,
|
||||
|
@ -25,7 +25,8 @@ namespace clang {
|
||||
class IdentifierInfo;
|
||||
class Preprocessor;
|
||||
class Declarator;
|
||||
|
||||
struct TemplateIdAnnotation;
|
||||
|
||||
/// DeclSpec - This class captures information about "declaration specifiers",
|
||||
/// which encompasses storage-class-specifiers, type-specifiers,
|
||||
/// type-qualifiers, and function-specifiers.
|
||||
@ -642,13 +643,7 @@ class UnqualifiedId {
|
||||
/// \param TemplateId the template-id annotation that describes the parsed
|
||||
/// template-id. This UnqualifiedId instance will take ownership of the
|
||||
/// \p TemplateId and will free it on destruction.
|
||||
void setTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
assert(TemplateId && "NULL template-id annotation?");
|
||||
Kind = IK_TemplateId;
|
||||
this->TemplateId = TemplateId;
|
||||
StartLocation = TemplateId->TemplateNameLoc;
|
||||
EndLocation = TemplateId->RAngleLoc;
|
||||
}
|
||||
void setTemplateId(TemplateIdAnnotation *TemplateId);
|
||||
|
||||
/// \brief Return the source range that covers this unqualified-id.
|
||||
SourceRange getSourceRange() const {
|
||||
|
@ -654,41 +654,33 @@ namespace clang {
|
||||
#endif
|
||||
};
|
||||
|
||||
class ParsedTemplateArgument;
|
||||
|
||||
class ASTTemplateArgsPtr {
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
ActionBase &Actions;
|
||||
#endif
|
||||
void **Args;
|
||||
bool *ArgIsType;
|
||||
ParsedTemplateArgument *Args;
|
||||
mutable unsigned Count;
|
||||
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
void destroy() {
|
||||
if (!Count)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i != Count; ++i)
|
||||
if (Args[i] && !ArgIsType[i])
|
||||
Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
|
||||
|
||||
Count = 0;
|
||||
}
|
||||
void destroy();
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
|
||||
ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
|
||||
unsigned count) :
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
Actions(actions),
|
||||
#endif
|
||||
Args(args), ArgIsType(argIsType), Count(count) { }
|
||||
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), ArgIsType(Other.ArgIsType), Count(Other.Count) {
|
||||
Args(Other.Args), Count(Other.Count) {
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
Other.Count = 0;
|
||||
#endif
|
||||
@ -700,7 +692,6 @@ namespace clang {
|
||||
Actions = Other.Actions;
|
||||
#endif
|
||||
Args = Other.Args;
|
||||
ArgIsType = Other.ArgIsType;
|
||||
Count = Other.Count;
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
Other.Count = 0;
|
||||
@ -712,22 +703,20 @@ namespace clang {
|
||||
~ASTTemplateArgsPtr() { destroy(); }
|
||||
#endif
|
||||
|
||||
void **getArgs() const { return Args; }
|
||||
bool *getArgIsType() const {return ArgIsType; }
|
||||
ParsedTemplateArgument *getArgs() const { return Args; }
|
||||
unsigned size() const { return Count; }
|
||||
|
||||
void reset(void **args, bool *argIsType, unsigned count) {
|
||||
void reset(ParsedTemplateArgument *args, unsigned count) {
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
destroy();
|
||||
#endif
|
||||
Args = args;
|
||||
ArgIsType = argIsType;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
void *operator[](unsigned Arg) const { return Args[Arg]; }
|
||||
const ParsedTemplateArgument &operator[](unsigned Arg) const;
|
||||
|
||||
void **release() const {
|
||||
ParsedTemplateArgument *release() const {
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
Count = 0;
|
||||
#endif
|
||||
|
@ -114,7 +114,7 @@ class Parser {
|
||||
~Parser();
|
||||
|
||||
const LangOptions &getLang() const { return PP.getLangOptions(); }
|
||||
TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
|
||||
const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
|
||||
Preprocessor &getPreprocessor() const { return PP; }
|
||||
Action &getActions() const { return Actions; }
|
||||
|
||||
@ -179,6 +179,8 @@ class Parser {
|
||||
/// the EOF was encountered.
|
||||
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
|
||||
|
||||
DeclGroupPtrTy RetrievePendingObjCImpDecl();
|
||||
|
||||
private:
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Low-Level token peeking and consumption methods.
|
||||
@ -331,7 +333,7 @@ class Parser {
|
||||
/// either "commit the consumed tokens" or revert to the previously marked
|
||||
/// token position. Example:
|
||||
///
|
||||
/// TentativeParsingAction TPA;
|
||||
/// TentativeParsingAction TPA(*this);
|
||||
/// ConsumeToken();
|
||||
/// ....
|
||||
/// TPA.Revert();
|
||||
@ -783,6 +785,7 @@ class Parser {
|
||||
AttributeList *prefixAttrs = 0);
|
||||
|
||||
DeclPtrTy ObjCImpDecl;
|
||||
llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl;
|
||||
|
||||
DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
|
||||
DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc);
|
||||
@ -1226,13 +1229,18 @@ class Parser {
|
||||
Parser &P;
|
||||
CXXScopeSpec &SS;
|
||||
bool EnteredScope;
|
||||
bool CreatedScope;
|
||||
public:
|
||||
DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss)
|
||||
: P(p), SS(ss), EnteredScope(false) {}
|
||||
: 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))
|
||||
SS.setScopeRep(0);
|
||||
|
||||
@ -1245,6 +1253,8 @@ class Parser {
|
||||
assert(SS.isSet() && "C++ scope was cleared ?");
|
||||
P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS);
|
||||
}
|
||||
if (CreatedScope)
|
||||
P.ExitScope();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1347,9 +1357,7 @@ class Parser {
|
||||
DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
|
||||
DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
|
||||
// C++ 14.3: Template arguments [temp.arg]
|
||||
typedef llvm::SmallVector<void *, 16> TemplateArgList;
|
||||
typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
|
||||
typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList;
|
||||
typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
|
||||
|
||||
bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
@ -1357,8 +1365,6 @@ class Parser {
|
||||
bool ConsumeLastToken,
|
||||
SourceLocation &LAngleLoc,
|
||||
TemplateArgList &TemplateArgs,
|
||||
TemplateArgIsTypeList &TemplateArgIsType,
|
||||
TemplateArgLocationList &TemplateArgLocations,
|
||||
SourceLocation &RAngleLoc);
|
||||
|
||||
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
|
||||
@ -1367,10 +1373,9 @@ class Parser {
|
||||
SourceLocation TemplateKWLoc = SourceLocation(),
|
||||
bool AllowTypeAnnotation = true);
|
||||
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
|
||||
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
|
||||
TemplateArgIsTypeList &TemplateArgIsType,
|
||||
TemplateArgLocationList &TemplateArgLocations);
|
||||
void *ParseTemplateArgument(bool &ArgIsType);
|
||||
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
|
||||
ParsedTemplateArgument ParseTemplateTemplateArgument();
|
||||
ParsedTemplateArgument ParseTemplateArgument();
|
||||
DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation &DeclEnd);
|
||||
|
@ -275,7 +275,8 @@ class Scope {
|
||||
AnyParent = Parent;
|
||||
Depth = AnyParent ? AnyParent->Depth+1 : 0;
|
||||
Flags = ScopeFlags;
|
||||
|
||||
WithinElse = false;
|
||||
|
||||
if (AnyParent) {
|
||||
FnParent = AnyParent->FnParent;
|
||||
BreakParent = AnyParent->BreakParent;
|
||||
@ -283,13 +284,10 @@ class Scope {
|
||||
ControlParent = AnyParent->ControlParent;
|
||||
BlockParent = AnyParent->BlockParent;
|
||||
TemplateParamParent = AnyParent->TemplateParamParent;
|
||||
WithinElse = AnyParent->WithinElse;
|
||||
|
||||
} else {
|
||||
FnParent = BreakParent = ContinueParent = BlockParent = 0;
|
||||
ControlParent = 0;
|
||||
TemplateParamParent = 0;
|
||||
WithinElse = false;
|
||||
}
|
||||
|
||||
// If this scope is a function or contains breaks/continues, remember it.
|
||||
|
183
include/clang/Parse/Template.h
Normal file
183
include/clang/Parse/Template.h
Normal file
@ -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
|
@ -14,6 +14,7 @@
|
||||
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@ -43,6 +44,10 @@ class CodeCompletionString {
|
||||
/// \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,
|
||||
@ -55,7 +60,29 @@ class CodeCompletionString {
|
||||
CK_Placeholder,
|
||||
/// \brief A piece of text that describes something about the result but
|
||||
/// should not be inserted into the buffer.
|
||||
CK_Informative
|
||||
CK_Informative,
|
||||
/// \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 One piece of the code completion string.
|
||||
@ -66,7 +93,7 @@ class CodeCompletionString {
|
||||
|
||||
union {
|
||||
/// \brief The text string associated with a CK_Text, CK_Placeholder,
|
||||
/// or CK_Informative chunk.
|
||||
/// 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;
|
||||
@ -79,21 +106,22 @@ class CodeCompletionString {
|
||||
|
||||
Chunk() : Kind(CK_Text), Text(0) { }
|
||||
|
||||
private:
|
||||
Chunk(ChunkKind Kind, const char *Text);
|
||||
|
||||
public:
|
||||
Chunk(ChunkKind Kind, llvm::StringRef Text = "");
|
||||
|
||||
/// \brief Create a new text chunk.
|
||||
static Chunk CreateText(const char *Text);
|
||||
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(const char *Placeholder);
|
||||
static Chunk CreatePlaceholder(llvm::StringRef Placeholder);
|
||||
|
||||
/// \brief Create a new informative chunk.
|
||||
static Chunk CreateInformative(const char *Informative);
|
||||
static Chunk CreateInformative(llvm::StringRef Informative);
|
||||
|
||||
/// \brief Create a new current-parameter chunk.
|
||||
static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
|
||||
|
||||
/// \brief Destroy this chunk, deallocating any memory it owns.
|
||||
void Destroy();
|
||||
@ -113,10 +141,28 @@ class CodeCompletionString {
|
||||
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(); }
|
||||
|
||||
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(const char *Text) {
|
||||
void AddTextChunk(llvm::StringRef Text) {
|
||||
Chunks.push_back(Chunk::CreateText(Text));
|
||||
}
|
||||
|
||||
@ -127,24 +173,46 @@ class CodeCompletionString {
|
||||
|
||||
/// \brief Add a new placeholder chunk.
|
||||
/// The placeholder text will be copied.
|
||||
void AddPlaceholderChunk(const char *Placeholder) {
|
||||
void AddPlaceholderChunk(llvm::StringRef Placeholder) {
|
||||
Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
|
||||
}
|
||||
|
||||
/// \brief Add a new informative chunk.
|
||||
/// The text will be copied.
|
||||
void AddInformativeChunk(const char *Text) {
|
||||
void AddInformativeChunk(llvm::StringRef Text) {
|
||||
Chunks.push_back(Chunk::CreateInformative(Text));
|
||||
}
|
||||
|
||||
/// \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 Retrieve a string representation of the code completion string,
|
||||
/// which is mainly useful for debugging.
|
||||
std::string getAsString() const;
|
||||
std::string getAsString() 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.
|
||||
static CodeCompletionString *Deserialize(llvm::StringRef &Str);
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
/// \brief Captures a result of code completion.
|
||||
struct Result {
|
||||
@ -291,23 +359,32 @@ class CodeCompleteConsumer {
|
||||
Sema &S) const;
|
||||
};
|
||||
|
||||
CodeCompleteConsumer() : IncludeMacros(false) { }
|
||||
|
||||
explicit CodeCompleteConsumer(bool IncludeMacros)
|
||||
: IncludeMacros(IncludeMacros) { }
|
||||
|
||||
/// \brief Whether the code-completion consumer wants to see macros.
|
||||
bool includeMacros() const { return IncludeMacros; }
|
||||
|
||||
/// \brief Deregisters and destroys this code-completion consumer.
|
||||
virtual ~CodeCompleteConsumer();
|
||||
|
||||
/// \name Code-completion callbacks
|
||||
//@{
|
||||
/// \brief Process the finalized code-completion results.
|
||||
virtual void ProcessCodeCompleteResults(Result *Results,
|
||||
virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
|
||||
unsigned NumResults) { }
|
||||
|
||||
/// \brief Process the set of overload candidates.
|
||||
|
||||
/// \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(unsigned CurrentArg,
|
||||
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) { }
|
||||
//@}
|
||||
@ -316,24 +393,43 @@ class CodeCompleteConsumer {
|
||||
/// \brief A simple code-completion consumer that prints the results it
|
||||
/// receives in a simple format.
|
||||
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
|
||||
/// \brief The semantic-analysis object to which this code-completion
|
||||
/// consumer is attached.
|
||||
Sema &SemaRef;
|
||||
|
||||
/// \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(Sema &S, llvm::raw_ostream &OS)
|
||||
: SemaRef(S), OS(OS) { }
|
||||
PrintingCodeCompleteConsumer(bool IncludeMacros,
|
||||
llvm::raw_ostream &OS)
|
||||
: CodeCompleteConsumer(IncludeMacros), OS(OS) { }
|
||||
|
||||
/// \brief Prints the finalized code-completion results.
|
||||
virtual void ProcessCodeCompleteResults(Result *Results,
|
||||
virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
|
||||
unsigned NumResults);
|
||||
|
||||
virtual void ProcessOverloadCandidates(unsigned CurrentArg,
|
||||
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, llvm::raw_ostream &OS)
|
||||
: CodeCompleteConsumer(IncludeMacros), 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);
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ namespace clang {
|
||||
class ASTContext;
|
||||
class CodeCompleteConsumer;
|
||||
class Sema;
|
||||
|
||||
|
||||
/// \brief Parse the entire file specified, notifying the ASTConsumer as
|
||||
/// the file is parsed.
|
||||
///
|
||||
@ -30,11 +30,13 @@ namespace clang {
|
||||
/// \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 *(*CreateCodeCompleter)(Sema &, void *Data) = 0,
|
||||
void *CreateCodeCompleterData = 0);
|
||||
CodeCompleteConsumer *CompletionConsumer = 0);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -35,7 +35,7 @@ enum FloatingRank {
|
||||
};
|
||||
|
||||
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
|
||||
TargetInfo &t,
|
||||
const TargetInfo &t,
|
||||
IdentifierTable &idents, SelectorTable &sels,
|
||||
Builtin::Context &builtins,
|
||||
bool FreeMem, unsigned size_reserve) :
|
||||
@ -256,9 +256,9 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
||||
= new (*this) MemberSpecializationInfo(Tmpl, TSK);
|
||||
}
|
||||
|
||||
UnresolvedUsingDecl *
|
||||
NamedDecl *
|
||||
ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
|
||||
llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>::iterator Pos
|
||||
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
|
||||
= InstantiatedFromUnresolvedUsingDecl.find(UUD);
|
||||
if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
|
||||
return 0;
|
||||
@ -268,7 +268,10 @@ ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
|
||||
|
||||
void
|
||||
ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
|
||||
UnresolvedUsingDecl *UUD) {
|
||||
NamedDecl *UUD) {
|
||||
assert((isa<UnresolvedUsingValueDecl>(UUD) ||
|
||||
isa<UnresolvedUsingTypenameDecl>(UUD)) &&
|
||||
"original declaration is not an unresolved using decl");
|
||||
assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
|
||||
"Already noted what using decl what instantiated from");
|
||||
InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
|
||||
@ -1186,7 +1189,7 @@ QualType ASTContext::getNoReturnType(QualType T) {
|
||||
}
|
||||
}
|
||||
|
||||
return getQualifiedType(ResultType, T.getQualifiers());
|
||||
return getQualifiedType(ResultType, T.getLocalQualifiers());
|
||||
}
|
||||
|
||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||
@ -2350,6 +2353,12 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
|
||||
return DTN->CanonicalTemplateName;
|
||||
}
|
||||
|
||||
bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
|
||||
X = getCanonicalTemplateName(X);
|
||||
Y = getCanonicalTemplateName(Y);
|
||||
return X.getAsVoidPointer() == Y.getAsVoidPointer();
|
||||
}
|
||||
|
||||
TemplateArgument
|
||||
ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
|
||||
switch (Arg.getKind()) {
|
||||
@ -2357,12 +2366,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
|
||||
return Arg;
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
// FIXME: Build canonical expression?
|
||||
return Arg;
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
|
||||
|
||||
case TemplateArgument::Template:
|
||||
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
return TemplateArgument(*Arg.getAsIntegral(),
|
||||
getCanonicalType(Arg.getIntegralType()));
|
||||
@ -2427,7 +2438,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
|
||||
const ArrayType *ASTContext::getAsArrayType(QualType T) {
|
||||
// Handle the non-qualified case efficiently.
|
||||
if (!T.hasQualifiers()) {
|
||||
if (!T.hasLocalQualifiers()) {
|
||||
// Handle the common positive case fast.
|
||||
if (const ArrayType *AT = dyn_cast<ArrayType>(T))
|
||||
return AT;
|
||||
@ -2732,12 +2743,22 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static RecordDecl *
|
||||
CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id) {
|
||||
if (Ctx.getLangOptions().CPlusPlus)
|
||||
return CXXRecordDecl::Create(Ctx, TK, DC, L, Id);
|
||||
else
|
||||
return RecordDecl::Create(Ctx, TK, DC, L, Id);
|
||||
}
|
||||
|
||||
// getCFConstantStringType - Return the type used for constant CFStrings.
|
||||
QualType ASTContext::getCFConstantStringType() {
|
||||
if (!CFConstantStringTypeDecl) {
|
||||
CFConstantStringTypeDecl =
|
||||
RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("NSConstantString"));
|
||||
CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("NSConstantString"));
|
||||
|
||||
QualType FieldTypes[4];
|
||||
|
||||
// const int *isa;
|
||||
@ -2774,8 +2795,8 @@ void ASTContext::setCFConstantStringType(QualType T) {
|
||||
QualType ASTContext::getObjCFastEnumerationStateType() {
|
||||
if (!ObjCFastEnumerationStateTypeDecl) {
|
||||
ObjCFastEnumerationStateTypeDecl =
|
||||
RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__objcFastEnumerationState"));
|
||||
CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__objcFastEnumerationState"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
@ -2807,8 +2828,8 @@ QualType ASTContext::getBlockDescriptorType() {
|
||||
|
||||
RecordDecl *T;
|
||||
// FIXME: Needs the FlagAppleBlock bit.
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor"));
|
||||
T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
@ -2850,8 +2871,8 @@ QualType ASTContext::getBlockDescriptorExtendedType() {
|
||||
|
||||
RecordDecl *T;
|
||||
// FIXME: Needs the FlagAppleBlock bit.
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor_withcopydispose"));
|
||||
T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get("__block_descriptor_withcopydispose"));
|
||||
|
||||
QualType FieldTypes[] = {
|
||||
UnsignedLongTy,
|
||||
@ -2920,8 +2941,8 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
|
||||
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
|
||||
++UniqueBlockByRefTypeID << '_' << DeclName;
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name.str()));
|
||||
T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name.str()));
|
||||
T->startDefinition();
|
||||
QualType Int32Ty = IntTy;
|
||||
assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
|
||||
@ -2970,8 +2991,8 @@ QualType ASTContext::getBlockParmType(
|
||||
llvm::raw_svector_ostream(Name) << "__block_literal_"
|
||||
<< ++UniqueBlockParmTypeID;
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name.str()));
|
||||
T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name.str()));
|
||||
QualType FieldTypes[] = {
|
||||
getPointerType(VoidPtrTy),
|
||||
IntTy,
|
||||
@ -3053,6 +3074,54 @@ int ASTContext::getObjCEncodingTypeSize(QualType type) {
|
||||
return sz / getTypeSize(CharTy);
|
||||
}
|
||||
|
||||
/// getObjCEncodingForBlockDecl - Return the encoded type for this method
|
||||
/// declaration.
|
||||
void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
|
||||
std::string& S) {
|
||||
const BlockDecl *Decl = Expr->getBlockDecl();
|
||||
QualType BlockTy =
|
||||
Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
|
||||
// Encode result type.
|
||||
getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S);
|
||||
// Compute size of all parameters.
|
||||
// Start with computing size of a pointer in number of bytes.
|
||||
// FIXME: There might(should) be a better way of doing this computation!
|
||||
SourceLocation Loc;
|
||||
int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
|
||||
int ParmOffset = PtrSize;
|
||||
for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
|
||||
E = Decl->param_end(); PI != E; ++PI) {
|
||||
QualType PType = (*PI)->getType();
|
||||
int sz = getObjCEncodingTypeSize(PType);
|
||||
assert (sz > 0 && "BlockExpr - Incomplete param type");
|
||||
ParmOffset += sz;
|
||||
}
|
||||
// Size of the argument frame
|
||||
S += llvm::utostr(ParmOffset);
|
||||
// Block pointer and offset.
|
||||
S += "@?0";
|
||||
ParmOffset = PtrSize;
|
||||
|
||||
// Argument types.
|
||||
ParmOffset = PtrSize;
|
||||
for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E =
|
||||
Decl->param_end(); PI != E; ++PI) {
|
||||
ParmVarDecl *PVDecl = *PI;
|
||||
QualType PType = PVDecl->getOriginalType();
|
||||
if (const ArrayType *AT =
|
||||
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
|
||||
// Use array's original type only if it has known number of
|
||||
// elements.
|
||||
if (!isa<ConstantArrayType>(AT))
|
||||
PType = PVDecl->getType();
|
||||
} else if (PType->isFunctionType())
|
||||
PType = PVDecl->getType();
|
||||
getObjCEncodingForType(PType, S);
|
||||
S += llvm::utostr(ParmOffset);
|
||||
ParmOffset += getObjCEncodingTypeSize(PType);
|
||||
}
|
||||
}
|
||||
|
||||
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
|
||||
/// declaration.
|
||||
void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
||||
@ -4186,8 +4255,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
|
||||
return LHS;
|
||||
|
||||
// If the qualifiers are different, the types aren't compatible... mostly.
|
||||
Qualifiers LQuals = LHSCan.getQualifiers();
|
||||
Qualifiers RQuals = RHSCan.getQualifiers();
|
||||
Qualifiers LQuals = LHSCan.getLocalQualifiers();
|
||||
Qualifiers RQuals = RHSCan.getLocalQualifiers();
|
||||
if (LQuals != RQuals) {
|
||||
// If any of these qualifiers are different, we have a type
|
||||
// mismatch.
|
||||
@ -4394,7 +4463,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
unsigned ASTContext::getIntWidth(QualType T) {
|
||||
if (T == BoolTy)
|
||||
if (T->isBooleanType())
|
||||
return 1;
|
||||
if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
|
||||
return FWIT->getWidth();
|
||||
|
@ -30,6 +30,7 @@ add_clang_library(clangAST
|
||||
TemplateName.cpp
|
||||
Type.cpp
|
||||
TypeLoc.cpp
|
||||
TypePrinter.cpp
|
||||
)
|
||||
|
||||
add_dependencies(clangAST ClangDiagnosticAST)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user