Update clang to r89205.

This commit is contained in:
Roman Divacky 2009-11-18 14:59:57 +00:00
parent 8f57cb0305
commit b3d5a323a5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=199482
918 changed files with 27089 additions and 11679 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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.

View File

@ -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

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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,

View File

@ -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

View File

@ -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.

View File

@ -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"

View File

@ -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)

View File

@ -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; }

View File

@ -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;
}

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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) { }

View File

@ -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();
}
};
}

View File

@ -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;

View File

@ -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:

View File

@ -17,6 +17,7 @@
#include "clang/AST/TypeLoc.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/ASTContext.h"
namespace clang {

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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"

View File

@ -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();
}

View File

@ -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() {}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
};

View File

@ -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,

View File

@ -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,

View File

@ -77,6 +77,8 @@ class MemRegion : public llvm::FoldingSetNode {
const MemRegion *getBaseRegion() const;
const MemRegion *StripCasts() const;
bool hasStackStorage() const;
bool hasParametersStorage() const;

View File

@ -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 {

View File

@ -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?

View File

@ -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;
}
};

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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'">;
}

View File

@ -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;

View File

@ -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]>;

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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">;

View File

@ -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<

View File

@ -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;
}

View File

@ -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, $@) $<

View File

@ -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.

View 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

View 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

View File

@ -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);
}

View File

@ -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.

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View 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

View File

@ -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);
};

View 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

View 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

View 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

View File

@ -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;
}
};

View 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

View 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

View 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

View 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

View 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

View File

@ -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.

View File

@ -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);
}

View 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

View 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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View 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

View File

@ -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; }

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -57,6 +57,7 @@ class AttributeList {
AT_analyzer_noreturn,
AT_annotate,
AT_blocks,
AT_cdecl,
AT_cleanup,
AT_const,
AT_constructor,

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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.

View 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

View File

@ -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);
};

View File

@ -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

View File

@ -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();

View File

@ -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